You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 51 Next »

Denne oppgaven handler om simulering av objekter i rommet, hvor en bruker arv både til rom-objektene og til rom-verdenen.


Merk: Denne oppgaven krever at tilleggspakken e(fx)clipse er installert! Hent lenke til update-site fra listen over tilleggspakker og installer e(fx)clipse. Tilleggspakkene kan finnes her: Eclipse-tillegg 

Simulering er en nyttig teknikk for å prøve ut ens forståelse av et fenomen, f.eks. fysikk. Enkelt sagt består en simulering av regler for hvordan objekter i en verden oppfører seg (både for seg selv og hvordan de spiller sammen), og en konkret verden i form av en start-konfigurasjon av objekter. Så tenker en seg at tiden går i små steg, og for hvert steg så oppdaterer en objektene i henhold til reglene.

I denne øvingen består verdenen av objekter (asteroider og en sol) som svever fritt i rommet og et romskip med motorer som kan snurre og skyve. Alle objekter har en posisjon, fart og masse, og virker på hverandre i henhold til formelen for gravitasjon. Romskipet har i tillegg vinkelfart og mulighet for å fyre av motorer bak (dytter) og på siden (snurrer).

 

Fil-tre som må lastes ned evt. importeres med Digital Compendium-panelet
emfs
/inheritance/ #java #package #test
        SpaceObjectTest.java                           @ git@github.com:hallvard/jexercise/no.hal.jex.collection/src-gen/inheritance/SpaceObjectTest.java;
        SpaceObject.jextest                           @ git@github.com:hallvard/jexercise/no.hal.jex.collection/tests/inheritance/SpaceObject.jextest;
Fil-tre som må lastes ned evt. importeres med Digital Compendium-panelet
emfs
/inheritance/ #java #package
	BaseSpaceObject.java			 	@ git@github.com:hallvard/jexercise/no.hal.jex.collection/src/inheritance/BaseSpaceObject.java;
        Asteroids.java			 	@ git@github.com:hallvard/jexercise/no.hal.jex.collection/src/inheritance/Asteroids.java;
        AsteroidsProgram.java			 	@ git@github.com:hallvard/jexercise/no.hal.jex.collection/src/inheritance/AsteroidsProgram.java;

 

Del 1 - Rom-objekter

SpaceObjectPoint2D positionPoint2D speeddouble getMass()Asteroiddouble densitydouble radiusSpaceShipdouble angleSpeed

Det er i hovedsak to typer rom-objekter, de som svever fritt (planeter, asteroider og stjerner) og romskipet, som har motorkraft. Det som er felles for alle rom-objektene ønsker vi å samle i superklassen SpaceObject, som de to mer spesialiserte typene Asteroid og SpaceShip arver fra. Dette er illustrert i diagrammet til venstre. Vi har brukt typen Point2D for å angi at posisjon (position) og fart (speed) beskrives av to verdier (koordinatpar/vektorkoordinater). Massen beregnes, så den er angitt som en operasjon og ikke som et attributt.

Det som ikke kommer frem i dette diagrammet er hvordan vi også ønsker å bygge på Polygon-klassen i JavaFX, for å gjøre det lettere å vise rom-objektene som grafikk i et vindu på skjermen. Med Polygon som superklasse for SpaceObject, så vil en kunne angi et sett punkter som utgjør konturen til rom-objektene. Siden Polygon i praksis også har en posisjon (i kraft av å være en Node), så trenger en ikke lagre denne som et eget felt i SpaceObject, så den faktiske implementasjon blir litt annerledes enn vist til venstre. Og for å gjøre det litt lettere å utnytte mulighetene i Polygon-klassen (spesielt koordinat-håndtering er litt fiklete), så har vi lage en hjelpeklasse, kalt BaseSpaceObject, som kan brukes som den direkte superklassen til SpaceObject og som selv arver fra Polygon. Dette er illustrert til høyre.

Kode m/dokumentasjon for BaseSpaceObject-klassen finner du nederst på denne siden.

De spesifikke metodene i SpaceObject, Asteroids og SpaceShip, som du må implementere er som følger:

SpaceObject

  • Point2D getSpeed() - returnerer farten som et (vektor)koordinatpar-objekt.
  • setSpeed(double vx, double vy) - setter farten til den angitt vektoren [vx, vy].
  • accelerate(double ax, double ay) - øker farten med den angitte akselerasjonsvektoren
  • double getMass() - returnerer massen, som er 0 hvis ikke annet er angitt.
  • applyForce(double fx, double fy) - justerer objektet iht. den angitte kraftvektoren. Dersom massen er 0, så skal det utløses et unntak av typen IllegalStateException.
  • boolean intersects(SpaceObject other) - returnerer true dersom den andre SpaceObject-instansen overlapper (kolliderer) med denne instansen, ellers false. Se eget avsnitt lenger ned.
  • void tick() - denne metoden kalles for hvert steg i simuleringen og skal justere alle dynamiske egenskaper iht. reglene for verdenen, f.eks. posisjon basert på farta.

Asteroid

  • public Asteroid(double density, double radius) - initialiserer tetthet og radius. Lag gjerne flere konstruktører, for å gjøre det lettere å lage asteroider med ulike konturer.
  • double getMass() - beregner massen fra tetthet og radius.

SpaceShip

  • SpaceShip() - initialiserer vinkelfarta til 0.
  • double getMass() - massen er alltid 1.
  • sidewaysThrust(double thrust) - endrer vinkelfarta tilsvarende. Positiv verdi gir fart mot urvisere. (Hint: bruk get/setRotate-metodene i Polygon).
  • forwardThrust(double thrust) - øker farta tilsvarende i retningen romskipet peker.
Polygon (fra JavaFX)Point2D positionPoint2D (fra JavaFX)BaseSpaceObjectSpaceObjectPoint2D speeddouble getMass()Asteroiddouble densitydouble radiusSpaceShipdouble angleSpeedpoints*

intersects-metoden

intersects-metoden skal returnere true dersom to SpaceObject-instanser (this og argumentet) overlapper. Sjekk for overlapp kan gjøres på mange måter, f.eks. sjekke overlapp av såkalt "bounding box" (minste omsluttende rektangel) eller om midten og/eller hjørnene i det ene polygonet er inni det andre (og vice versa), eller en kombinasjon av flere av disse. contains-metoden BaseSpaceObject i er nyttig her. Enkle teknikker vil dekke mange relevante tilfeller, men for å ta alle hjørnetilfellene (wink) så må en være litt kløktig og kombinere flere typer teknikker. Figuren til høyre viser fire polygoner som har litt ulik type overlapp og tabellen bortenfor viser hvilke som overlapper (fasit for testkoden).

  • De blå, grønne og røde polygonene overlapper, og her vil en "bounding box"-test fungere. Men en slik test vil også gi overlapp med den gule, og det stemmer jo ikke.
  • En test for om hjørnene til den ene er inni den andre (og vice versa), vil fungere for de fleste, men ikke for den røde og grønne.
  • En test for om midt-punktet til den ene er inni den andre (og vice versa), vil fungere for de fleste, men ikke for den grønne og gule.

Det som altså fungerer best er en kombinasjon av alle disse teknikkene!

 Blå (so1)Grønn (so2)Rød (so3)Gul (so4)
Blåxxx 
Grønnxxxx
Rødxxx 
Gul x x
 

JExercise-testkode og originalkoden (jextest er tilgjengelig i emfs-filtreet i starten av oppgaven.

 

Del 2 - Oppsett av verden og simulering

Pane (fra JavaFX)AsteroidsSpaceObjectAsteroids1Asteroids2Asteroids3spaceObjects*

Denne delen tar utgangspunkt i en delvis ferdigskrevet Asteroids-klasse. Oppgaven til Asteroids-klassen er todelt: 1) å rigge opp verdenen med rom-objekter og 2) kjøre selve simuleringen. I koden for Asteroids-klassen, som ligger nederst på denne siden, legges det opp til at dette gjøres i henholdsvis init()- og run()-metoden, men du står forsåvidt fritt til å (gjen)bruke denne koden som du vil. Men for at du skal lære mest mulig om arv, så prøv å legge mest mulig av din egen kode i subklasser av Asteroids, heller enn å skrive den om. Vi foreslår at du gjør oppgaven i følgende trinn, med én subklasse pr. trinn.

Astroids-klassen har noen finesser, som kan nyttige ved feilsøking:

  • trykk '+' og '-' for zoome inn og ut
  • trykk ' ' (mellomrom) for å stoppe/starte simuleringen og '>' for å kjøre ett steg (tick)

Bruk AsteroidsProgram som hovedprogramklasse. Du kan hvis du vil bruke main-metoden til AsteroidsProgram, som tar inn navnet til Asteroids-(sub)klassen som eneste programargument. Det enkleste er kanskje å lage en main-metode i din egen Asteroids-(sub)klasse (her kalt Asteroids1), slik:

public static void main(String[] args) {
   AsteroidsProgram.main(new String[]{inheritance.Asteroids1.class.getName()}); // lager en String-tabell med klassenavnet som eneste element
}

Trinn 1 - Asteroids1

I dette trinnet er målet å få lagt inn noen SpaceObject-instanser, se (til) at simuleringen beveger dem på skjermen og få kollisjonsdeteksjon til å fungere.

SpaceObject-instansene opprettes i init()-metoden og legges inn med den ferdigskrevne add-metoden i Asteroids-klassen. For å få simuleringen til å virke, så må du fylle inn kode i tick()-metoden:

  • For hvert SpaceObject må du utføre ett simuleringstrinn.
  • For hvert SpaceObject-par må du sjekke for kollisjon, altså om de overlapper hverandre (se intersects-metoden i SpaceObject-klassen over).

Se http://stackoverflow.com/questions/345838/ball-to-ball-collision-detection-and-handling dersom du vil simulere kollisjoner som (fullstendig) elastiske støt.

Trinn 2 - Asteroids2

I dette trinnet er målet å få gravitasjonslogikken til å fungere og sjekke det ved å legge inn en sol (stor, gul og rund Asteroid-instans) og masse asteroider (Asteroid-instanser av med ulik tetthet og størrelse).

Utvid tick()-metoden slik at du for hvert SpaceObject-par beregner og håndterer den gjensidige gravitasjonskraften.

Trinn 3 - Asteroids3

I dette trinnet implementerer du støtte for å styre romskipet med piltastene (KeyCode.LEFTKeyCode.RIGHT og KeyCode.UP). Finn selv ut hvilke Asteroids-metoder som må redefineres, for å få dette til. Sørg for å legge til et romskip og prøv å unngå å kollidere eller å bli fanget av sola!

Fil-tre som må lastes ned evt. importeres med Digital Compendium-panelet
emfs
/inheritance/ #java #package
	BaseSpaceObject.java			 	@ git@github.com:hallvard/jexercise/no.hal.jex.collection/src/inheritance/BaseSpaceObject.java;
        Asteroids.java			 	@ git@github.com:hallvard/jexercise/no.hal.jex.collection/src/inheritance/Asteroids.java;
        AsteroidsProgram.java			 	@ git@github.com:hallvard/jexercise/no.hal.jex.collection/src/inheritance/AsteroidsProgram.java;
        ;
/inheritance/ #java #package #test
        SpaceObjectTest.java                           @ git@github.com:hallvard/jexercise/no.hal.jex.collection/src-gen/inheritance/SpaceObjectTest.java;
        SpaceObject.jextest                           @ git@github.com:hallvard/jexercise/no.hal.jex.collection/tests/inheritance/SpaceObject.jextest;
  • No labels