Programmering

Animasjon i Java-appletter

Denne artikkelen beskriver hvordan du implementerer animasjon ved hjelp av Java applet API. Den beskriver ofte brukte teknikker og gir et enkelt eksempel for å illustrere hver teknikk.

Grunnleggende animasjonsteknikker

Mange former for animasjon er mulig i Java. Felles for dem alle er at de skaper en slags bevegelse på skjermen ved å tegne suksessive rammer med relativt høy hastighet (vanligvis omtrent 10-20 ganger per sekund).

Vi starter med å lage en enkel mal-applet for å gjøre animasjoner og sakte utarbeide den til vi kommer til en ganske komplett applet.

Ved hjelp av en tråd

For å oppdatere skjermen flere ganger i sekundet, må du opprette en ny Java-tråd som inneholder en animasjonssløyfe. Animasjonssløyfen er ansvarlig for å holde rede på gjeldende ramme og for å be om periodiske skjermoppdateringer. For å implementere en tråd, må du enten lage en underklasse av Tråd eller overholde Kjørbar grensesnitt.

En vanlig feil er å sette animasjonssløyfen i maling() metoden til en applet. Å gjøre det vil ha rare bivirkninger fordi det holder hoved AWT-tråden, som er ansvarlig for all tegning og håndtering av hendelser.

Som et eksempel har jeg skrevet en liten malapplet, kalt Example1Applet, som illustrerer den generelle oversikten til en animasjonsapplet. Eksempel1Applet viser hvordan du oppretter en tråd og kaller male på nytt () metode med faste intervaller. Antall bilder per sekund spesifiseres ved å sende inn en appletparameter. Her er et eksempel på hva du vil legge i HTML-dokumentet:

Her er eksempel1applet.

Merk:

Denne appleten tegner faktisk ikke noe på skjermen ennå. Tegning til skjermen forklares senere. Vær også oppmerksom på at appleten ødelegger animasjonstråden når brukeren forlater siden (noe som resulterer i appleten Stoppe() metoden blir kalt). Dette sikrer at appleten ikke kaster bort CPU-tid mens siden ikke er synlig.

Holde en konstant bildefrekvens

I eksemplet ovenfor sover appleten bare i en fast tid mellom rammer. Dette har den ulempen at du noen ganger venter for lenge. For å få 10 bilder per sekund bør du ikke vente 100 millisekunder mellom bildene, fordi du taper litt tid på å bare kjøre tråden.

Følgende applet, Example2Applet, viser hvordan du holder bedre tid. Den beregner ganske enkelt riktig forsinkelse mellom rammer ved å holde oversikt over starttiden. Den beregner den estimerte nødvendige forsinkelsen mellom rammer basert på gjeldende tid.

Her er eksempel2applet.

Maling av hver ramme

Det som gjenstår er å male hver ramme. I de forrige eksemplene kaller vi male på nytt () for hver ramme, noe som forårsaker appletens maling() metoden som skal kalles. Example3Applet har en maling() metode som trekker nummeret til den nåværende rammen til skjermen.

Her er Example3Applet i aksjon, etterfulgt av en kodeliste.

Merk:

Hvis du angir at bildefrekvensen er veldig høy (si 100 bilder per sekund), blir løpe() metoden vil ringe male på nytt () 100 ganger i sekundet. Dette vil imidlertid ikke alltid resultere i 100 samtaler til maling() per sekund fordi når du sender forespørsel om maling for raskt, vil de bli kollapset til en enkelt skjermoppdatering. Dette er grunnen til at vi holder rede på gjeldende rammenummer i løpe() metoden heller enn i maling() metode.

Genererer grafikk

La oss nå animere noe som er litt vanskeligere å tegne. Example4Applet tegner en kombinasjon av sinusbølger. For hver x-koordinat trekker den en kort vertikal linje. Alle disse linjene danner sammen en enkel graf som endres for hver ramme. Dessverre vil du oppdage at denne tilnærmingen forårsaker mye blink. Vi forklarer årsaken til blinkingen og noen løsninger i neste avsnitt.

Her er Example4Applet i aksjon, etterfulgt av en kodeliste.

Unngå overdreven blinking

Blinkingen du ser i Eksempel 4Applet har to årsaker: å male hver ramme tar for lang tid (på grunn av mengden beregning som kreves under ommaling), og hele bakgrunnen blir ryddet før maling() er kalt. Mens beregningen av neste ramme pågår, ser brukeren bakgrunnen til animasjonen.

Denne korte tiden mellom rydding av bakgrunnen og maling av sinusbølgen blir sett på som et blits. På noen plattformer som PC-en er blinkingen mer åpenbar enn den er på X Windows. Årsaken er at X Windows-grafikken er bufret, noe som gjør blitsen litt kortere.

Du kan redusere blinkingen sterkt ved å bruke to enkle triks: implementering av Oppdater() metode og bruk av dobbel buffering (noen ganger kjent som ved hjelp av en tilbakeslagsholder).

Overstyring av oppdateringsmetoden

Når AWT mottar en forespørsel om ny maling for en applet, kaller den appleten Oppdater() metode. Som standard er Oppdater() metoden tømmer appletens bakgrunn og kaller deretter maling() metode. Ved å overstyre Oppdater() metode for å inkludere tegningskoden som pleide å være i maling() metoden, unngår vi å rydde hele appleten med hver maling.

Nå som bakgrunnen ikke lenger blir ryddet automatisk, må vi gjøre det selv i Oppdater() metode. Vi kan nå slette hver loddrett linje i grafen hver for seg før vi tegner den nye linjen, og eliminere blinkingen helt. Denne effekten vises i eksempel 5Applet.

Her er Example5Applet i aksjon, etterfulgt av en kodeliste.

Merk:

Når du overstyrer Oppdater() metode, må du fortsatt implementere maling(). Dette er fordi maling() metoden kalles direkte av AWT-tegnesystemet når "skader" oppstår i appletens tegneområde - for eksempel når et vindu som skjuler en del av appletens tegneområde, blir fjernet fra skjermen. Din maling() implementering kan bare ringe Oppdater().

Dobbelt buffering

En annen måte å redusere blinkingen mellom rammer er å bruke dobbel buffering. Denne teknikken brukes i mange animasjonsapplets.

Det generelle prinsippet er at du lager et skjermbilde, du tegner en ramme inn i bildet, og deretter slår du hele bildet på skjermen med en samtale til drawImage (). Fordelen er at det meste av tegningen gjøres utenfor skjermen. Det endelige maleriet av skjermbildet på skjermen er vanligvis mye mer effektivt enn å male rammen direkte på skjermen.

Sinusbølgeapplet med dobbel buffering er vist i Eksempel 6Applet. Du vil se at animasjonen er ganske jevn, og at du ikke trenger noen spesielle triks når du tegner rammen. Den eneste ulempen er at du må tildele et skjermbilde som er like stort som tegneområdet. Hvis tegneområdet er veldig stort, kan dette kreve ganske mye minne.

Her er eksempel 6 applet i aksjon, etterfulgt av en kodeliste.

Merk:

Når du bruker dobbel buffering, må du overstyre Oppdater() metode, siden du ikke vil at appletens bakgrunn skal tømmes før du maler rammen. (Du rydder bakgrunnen selv ved å tegne til bildet utenfor skjermen.)

Bruke bilder

Nå skal vi skrive om paintFrame () metode med en metode som animerer noen bilder. Dette gir noen mindre komplikasjoner til problemet. Bildene er ganske store, og de lastes trinnvis. Det kan ta lang tid før bilder blir tegnet helt, spesielt når du laster dem over en treg forbindelse. Dette er grunnen til at drawImage () metoden tar et fjerde argument, et ImageObserver-objekt. Bildebehandleren er et objekt som blir varslet når flere av bildedataene har kommet. For å få bildene bruker vi getImage () metode.

Flytte et bilde over skjermen

Denne første bildeanimerende appleten, Example7Applet, bruker følgende to bilder:

world.gif: car.gif:

Verdensbildet brukes som bakgrunn, og bilbildet tegnes to ganger på toppen av det, og skaper en animasjon av to biler som løper over hele verden.

Her er eksempel 7 applet i aksjon, etterfulgt av en kodeliste.

Viser en sekvens av bilder

Example8Applet viser hvordan du lager en animasjon ved hjelp av separate bilder for hver ramme. Her er de 10 rammene som brukes:

T1.gif: T2.gif: T3.gif: T4.gif: T5.gif:

T6.gif:

T7.gif:

T8.gif:

T9.gif:

T10.gif:

Vi bruker fortsatt dobbel buffering for å eliminere blinking. Årsaken er at hvert bilde vi gjengir er delvis gjennomsiktig, og vi må derfor slette hver ramme før vi tegner det neste. Dette vil føre til blinking uten dobbel buffering.

Her er eksempel8applet i aksjon, etterfulgt av en kodeliste.

Merk:

Når du viser bildesekvenser, må du være forsiktig med å justere bildene riktig. Den enkleste måten er å sørge for at bildene har samme størrelse og kan tegnes i samme posisjon. Hvis det ikke er tilfelle, må appleten din tegne hver ramme med en annen forskyvning.

Bruke MediaTracker for å unngå trinnvis visning

Når et Java-program laster inn et bilde, kan det vise bildet før bildet er fullstendig lastet inn. Brukeren ser at bildet blir gjengitt først ufullstendig, og deretter trinnvis mer og mer fullstendig når bildet lastes inn. Denne inkrementelle skjermen gir brukeren tilbakemeldinger (forbedrer opplevd ytelse) og lar programmet enkelt utføre andre oppgaver mens bildet lastes inn.

Når det gjelder animasjon, kan inkrementell bildevisning være nyttig for bakgrunnsbilder, men det kan være veldig distraherende når det brukes til de animerte bildene. Noen ganger er det derfor ønskelig å vente til hele animasjonen er lastet før den vises.

Du kan bruke Jim Graham's MediaTracker klasse for å spore nedlasting av bilder, og forsinke animasjonsvisningen til hele bildesettet er fullstendig lastet ned. Eksempel9Applet viser hvordan du bruker MediaTracker klasse for å laste ned bilder for den vinkende Duke-animasjonen.

Her er eksempel 9 applet i aksjon, etterfulgt av en kodeliste.

Legger til lyd

Det er enkelt å legge til lyd i en animasjon. Du kan bruke getAudioClip () metode for å få et AudioClip-objekt. Senere kan du spille av klippet enten som en kontinuerlig sløyfe eller som en enkelt lyd. Eksempel10Applet viser hvordan du spiller en kontinuerlig bakgrunnslyd så vel som en repeterende lyd under animasjonen.

Her er eksempel 10Applet i aksjon, etterfulgt av en kodeliste.

Merk:

Når du spiller av en kontinuerlig lyd, må du huske å stoppe den når brukeren forlater siden (dvs. gjør det i appleten din Stoppe() metode).

En annen merknad:

Kontinuerlig lyd kan være veldig irriterende. Det er en god ide å gi brukeren en måte å slå av lyden uten å forlate siden. Du kan gi en knapp, eller bare slå av lyden når brukeren klikker i appleten.

Tips for raskere lasting av bilder

Det tar lang tid å laste ned en animasjon som bruker mange bilder. Dette skyldes hovedsakelig at det opprettes en ny HTTP-tilkobling for hver bildefil, og det kan ta flere sekunder å opprette en forbindelse selv når det er rikelig med båndbredde.

I denne delen vil vi fortelle deg om to bildeformater appleten din kan bruke til å gjøre nedlasting av bilder raskere.

Bruke en bildestripe

Du kan forbedre nedlastingsytelsen ved å bruke et enkelt bilde som inneholder flere animasjonsrammer. Du kan gjengi en enkelt ramme ut av bildet ved å bruke clipRect () operatør. Nedenfor er et eksempel på en bildestripe som brukes i UnderConstruction-appleten.

Appleten skaper en boreeffekt ved ikke å slette de forrige bildene. Bakgrunnen tømmes bare så ofte.

Her er UnderConstruction i aksjon, med en lenke til kildekoden.

Inter-frame komprimering ved hjelp av Flic

Hvis du virkelig ønsker å forbedre nedlastingsytelsen til en animasjon som består av flere rammer, må du bruke en eller annen form for komprimering mellom rammer.

Animasjonsverktøy

For øyeblikket (januar 1996) er det få verktøy tilgjengelig som hjelper deg med å lage Java-drevne animasjoner. Det beste verktøyet jeg kunne finne er DimensionX's The Easy Animator (TEA) (tidligere kjent som JAM). Den lar deg lage animasjoner interaktivt. Vi vil oppfordre utviklere til å skrive flere verktøy for å lage animasjoner i Java.

Hvis du har noen ferdige bilder å vise, kan du bruke animator-appleten. Animator har mange parametere som lar deg spesifisere kontinuerlige lyder, rammespesifikke lyder, individuell rammetid og posisjoner, et oppstartsbilde, rammeordre og så videre.

Du bør også sjekke ut Gamelan Animation-siden for å finne mange applets som bruker animasjon.

Konklusjon

Jeg håper denne artikkelen vil hjelpe appletutviklere til å skrive flere og bedre animasjonsapplets. Jeg håper også at bedre verktøy snart vil bli tilgjengelig.

Arthur van Hoff var inntil nylig senioringeniør i Sun Microsystems og har vært involvert i utviklingen av Java-språket siden 1993. Han er forfatter av den første Java-kompilatoren som er skrevet helt på Java. Han forlot nylig Sun for å danne et nytt selskap sammen med Sami Shaio, Kim Polese og Jonathan Payne. Det nye selskapet vil fokusere på å bygge Java-applikasjoner. Kathy Walrath er teknisk forfatter på Sun Microsystems. Hun har vært en del av Java-teamet siden 1993. For tiden jobber hun med Mary Campione på The Java Tutorial: Object-Oriented Programming for the Internet, en appletforbedret opplæring for å lære Java-språket, appletprogrammering og Java GUI-programmering. . Foruten å være tilgjengelig online, vil Java Tutorial også bli publisert i sommer som en del av Addison-Wesley Java Series.

Denne historien, "Animasjon i Java-appletter" ble opprinnelig utgitt av JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found