Pelissä ohjataan avaruusalusta (sininen kulmikas juttu) ja väistellään asteroideja (punaiset pallot). Pelin voittaa jos aika loppuu
Toimii applettina eli tälläinen pitää olla html sivulla joka on samassa kansiossa class tiedostojen kanssa:
AsteroidEngaged.html:
<APPLET CODE="AsteroidEngaged.class" WIDTH=500 HEIGHT=500></APPLET>
AsteroidEngaged.java
/*Pelissä ohjataan nuolinäppäimillä avaruusalusta *Peli on rakennettu apletiksi joten sitä pitää käyttää *nettiselaimella jossa on oikea koodin pätkä *<APPLET CODE="AsteroidEngaged.class" WIDTH=500 HEIGHT=500></APPLET> *Pelissä on kolme luokkaa Alus joka kuvaa avaruusalusta AsteroidEngagend *tämä joka on pääluokka ja keskeinen Kivi kuvaa yhtä kiveä joita on monta *Tämä luokka perii appletin tästä johtuen toimii vain nettiympäristössä *Pelin voi helposti kääntää Muualle toimivaksi jos laittaa appletin paikalle *panelin ja muuttaa paria asiaa. *Pelissä on siis säie joka tässä toteutetaan niin, että AsteroidEngagted toteuttaa *Runnable rajapinnan ja sisältää metodin run(). *Pelissä on kaksi kuuntelijaa näppäimistö ja focus. Molemmat on toteutettu *luomalla kuuntelija new tyyliin. Toinen vaihtoehto olisi ollut pistää luokka *toteuttaan kuuntelijat kuten runnable ja lisäämällä metodit luokan sisään. *Pelissä on käytetty puskuria piirtämisen yhteydessä. Se vähentää värähtelyä joka *häiritsee silmää * *tjn teki tämän pelin*/ import java.awt.*; import java.applet.*; import java.awt.event.*; public class AsteroidEngaged extends Applet implements Runnable{ private Alus alus; private Kivi[] kivet; //kivet ovat taulukossa private int indeksi=0; //indeksi nopeuttaa taulukkoa private int aika=100; //kun aika menee nollaan on voittanut //Aika ei välttämättä ole aivan sekunnilleen oikein riippuen koneen //nopeudesta yleensä vähän hitaampia sekuntteja private boolean havinnyt=false; //totuusarvo joka tulee kin on hävinnyt private int paras=0; //parahaat pisteet tällä kertaa private boolean focus=false; //tulee myöhemmin private Thread thread =new Thread(this); //Säie tekee pelistä liikkuvan //Käynnistetään kun näpäyttää peliä public void init() { this.kivet=new Kivi[100]; //sata kiveä this.alus=new Alus(); Color vari=new Color(0,0,0); this.setBackground(vari); //musta tausta KeyListener kuuntelija=new KeyAdapter(){ //tässä tehdään näppäimistön //kuuntelu public void keyPressed(KeyEvent e){ //näppäin alas if (e.getKeyCode()==KeyEvent.VK_RIGHT){ liikuO(true); //täältä ei voinut jostain //syystä kutsua private //kenttiä } if (e.getKeyCode()==KeyEvent.VK_LEFT){ liikuV(true); } } public void keyReleased(KeyEvent e){ //näppäin ylos liikuO(false); liikuV(false); } }; addKeyListener(kuuntelija); //Focus tulee kun painaa hiirellä aplettia //ja lähtee kun painaa apletin ulkopuolelle //näin ohjelma alkaa silloin kun käyttäjä haluaa FocusListener f = new FocusListener() { public void focusGained(FocusEvent e) { focus(true); thread.start(); //kutsutaan run metodia } public void focusLost(FocusEvent e) { focus(false); } }; this.addFocusListener(f); } public void focus(boolean fo){ focus=fo; } //run metodi tehdään kun toteutetaan runnable rajapinta public void run(){ //Kun koko ohjelmassa on vain yksi säie //niin seuraavat muuttujat toimivat apuna //esim tehdään joku joka viides kerta int muuttuja=0; int aikab=0; //ikuinen luuppi while(true){ //Ohjelma odottaa 0,02 sekunttia try{ Thread.currentThread().sleep(20); }catch(InterruptedException e){ } //jos ohjelmalla on foocus se toimii if(focus){ //kiveä kutsutaan joka 0,08 sec if(muuttuja==4){ kivi(); muuttuja=0; } muuttuja++; //kello siiryy joka 0,6 sec loput ajasta menee prosessorin //piikkiin if(aikab==30){ this.aika--; aikab=0; } aikab++; //liikuttaa alusta this.alus.liiku(); //pudottaa kaikkia kiviä vähän alas(); repaint(); //Kun törmää johonkin kiveen tulee tehdään seuraavaa if(this.havinnyt){ //piippaa Toolkit.getDefaultToolkit().beep(); //odottaa 2 sec try{ Thread.currentThread().sleep(2000); }catch(InterruptedException e){ } //kun tämä muutetaan niin peli taas aloittaa alusta this.havinnyt=false; //Oikeassa alakulmassa oleva paras tulos muuttuu jos //nykyinen tulos on sitä parmpi if(100-this.aika>this.paras){ this.paras=100-this.aika; } this.aika=100; } } } } //luo kiven ja pyörittää kivi taulukkoa niin, että alhaalla olevat kivet //menevät takaisin ylös public void kivi(){ this.kivet[this.indeksi] = new Kivi(); this.indeksi++; this.kivet[this.indeksi] = new Kivi(); this.indeksi++; if (this.indeksi>98){ indeksi=0; } } //liikuttaa kiviä alaspäin public void alas(){ for(int i=0;i<100 &&this.kivet[i]!=null&&this.aika>0;i++){ this.kivet[i].asetaY(this.kivet[i].getY()+5); //Jos kivi ja alus ovat samoilla paikoilla olet hävinnyt if(this.kivet[i].getY()<=400 && this.kivet[i].getY()>=380 && this.kivet[i].getX()<=this.alus.kerroPaikka()+26 && this.kivet[i].getX()>=this.alus.kerroPaikka()-8){ //kaikki kivet siirretään ulos kuvaruudusta for(int j=0;j<100 &&this.kivet[j]!=null;j++){ this.kivet[j].asetaY(500); } //kun tämä muuttuja on totta niin silloi peli pysähtyy hetkeksi //ja ilmottaa tuloksen ja alkaa taas this.havinnyt=true; } } } //näppäimistön kuuntelija tarvitsee seuraavia public void liikuO(boolean b){ if(b==true) this.alus.oikea(); else this.alus.stop(); } public void liikuV(boolean b){ if(b==true) this.alus.vasen(); else this.alus.stop(); } //kun appletilla on tämä metodi niin joka kerta kun kutsutaan repaint() //kaikkea ei pyyhitä. Eli ohjelma ei piirrä backgroundin väristä isoa neliötä public void update(Graphics g){ paint(g); } //korvaa apletin paint metodin piirtää kaiken public void paint(Graphics g) { //Tässä on puskuri sen avulla piirto sujuu sulavammin Image kuva=createImage(this.getWidth(), this.getHeight()); Graphics grafiikka=kuva.getGraphics(); grafiikka.setColor(Color.red); //Avaruusalusta esittää pelissä polygoni jolla on 12 kulmaa //tästä johtuen pitää tehdä taulukot joita tarvitaan myöhemmin //eli koordinaatit int[] xCoords = new int[12]; int[] yCoords = new int[12]; xCoords[0] = this.alus.kerroPaikka()+2; xCoords[1] = this.alus.kerroPaikka()+6; xCoords[2] = this.alus.kerroPaikka()+8; xCoords[3] = this.alus.kerroPaikka()+12; xCoords[4] = this.alus.kerroPaikka()+14; xCoords[5] = this.alus.kerroPaikka()+18; xCoords[6] = this.alus.kerroPaikka()+18; xCoords[7] = this.alus.kerroPaikka()+14; xCoords[8] = this.alus.kerroPaikka()+12; xCoords[9] = this.alus.kerroPaikka()+10; xCoords[10] = this.alus.kerroPaikka()+6; xCoords[11] = this.alus.kerroPaikka()+2; yCoords[0] = 380; yCoords[1] = 386; yCoords[2] = 380; yCoords[3] = 380; yCoords[4] = 386; yCoords[5] = 380; yCoords[6] = 400; yCoords[7] = 400; yCoords[8] = 396; yCoords[9] = 396; yCoords[10] = 400; yCoords[11] = 400; //jos peli on hävitty tai voitettu seuraavaa ei tehdä if(this.aika>0&&!this.havinnyt){ for(int i=0;i<100;i++){ if(this.kivet[i]!=null){ //puskuriin piirretään kiviä grafiikka.fillArc(this.kivet[i].getX()-10,this.kivet[i].getY()-10,20,20,0,360); } } grafiikka.setColor(Color.gray); //harmää viiva oikealla grafiikka.fillRect(410,0,3,500); grafiikka.setColor(Color.blue); //puskurille piirretään Polygoni grafiikka.fillPolygon(xCoords, yCoords, 12); //Aika piirretään seuraavassa String aikab=Integer.toString(this.aika); Font font=new Font("default", Font.BOLD, 24); grafiikka.setFont(font); grafiikka.drawString(" "+aikab,420,20); //paras tulos ilmoitetaan alakulmassa if(this.paras!=0){ grafiikka.drawString("Paras",420,350); grafiikka.drawString(" "+Integer.toString(this.paras),420,380); } //nyt puskuri piirretään apletille //kuva oli image jonka Grafiikka oli grafiikka g.drawImage(kuva,0,0,this); } //jos hävinnyt muuttuja on false ja kello on käynyt olet voittanut else if(!this.havinnyt){ //voittotekstit Font font=new Font("default", Font.BOLD, 24); grafiikka.setFont(font); grafiikka.drawString("LOPPU",100,200); grafiikka.setColor(Color.blue); grafiikka.fillPolygon(xCoords, yCoords, 12); g.drawImage(kuva,0,0,this); } //jos hävisit tulee ruudulle seuraavaa tekstiä else{ Font font=new Font("default", Font.BOLD, 24); grafiikka.setFont(font); grafiikka.drawString("Selviydyit "+(100-this.aika)+ " sekunttia",100,200); g.drawImage(kuva,0,0,this); } //Kun tällä apletilla ei ole focusta eli huomiota tulee alussa oleva teksti ruutuun if(!focus){ Font font=new Font("default", Font.BOLD, 24); grafiikka.setFont(font); grafiikka.drawString("Click here to start",50,200); grafiikka.drawString("Ohjaa nuolinäppäimillä",50,230); g.drawImage(kuva,0,0,this); } } }
Alus.java
//Alus on avaruus alus se sisältää koordinaatteja ja sitä voi liikutella public class Alus{ //alkupaikka = 200 private int paikka=200; private boolean oikea=false;//onko menossa oikealle private boolean vasen=false; public Alus(){ } //tästä saa ulkopuolinen luokka tietää paikan public int kerroPaikka(){ return this.paikka; } //Kutsutaan pääluokasta laittaa aluksen menemään oikealle mutta ei vielä //liikuta sitä. Kun oikea nappula napsautetaan alas public void oikea(){ if(paikka!=400){ this.oikea=true; } } //sama vasemmalle public void vasen(){ if (paikka!=0){ this.vasen=true; } } //kutsutaan kun jompikumpi nappula nostetaan ylös vasen tai oikea public void stop(){ this.vasen=false; this.oikea=false; } //liikuttaa alusta siihen suuntaa joka on valittu //tätä kutsutaan pääluokan run metodista public void liiku(){ if(this.oikea&&paikka<384){ this.paikka+=4; } else if(this.vasen&&paikka>0){ this.paikka-=4; } } }
Kivi.java
//kivi on kivi sillä on koordinaatteja ja sen konstruktori käyttää satunnais //generaattoria random() x tekemiseen //Kiven koordinaatit voi asettaa pääluokasta public class Kivi{ private int x; private int y; public Kivi(){ //99 eri paikkaa 396 leveydellä this.x=(int)(4*Math.random()*100+4); } public void asetaX(int x){ this.x=x; } public void asetaY(int y){ this.y=y; } //näillä ulkopuolinen luokka saa tiedot public int getX(){ return this.x; } public int getY(){ return this.y; } }
Ei kannata käyttää samaa nimeä metodille ja muuttujalle samanaikaisesti. Ihan mukava idea, vähä tökittää.
Oiskohan binääriä?
Perhana, selain kaatui ja siinä meni pitkät tekstit, eikä jaksa kirjoittaa kaikkea uudestaan :/
Mutta käännetty appletti löytyy nyt kuitenkin osoitteesta http://www.paivola.fi/~sami/java/Asteroid/
Pelin koodista vielä sen verran, että ainakin run-metodia voisi yrittää muuttaa hieman ei-purkkamaiseksi ja aluksen piirtämisen voisi tehdä alussa kertaalleen ja luoda siitä kuvan, jolloin sen voisi paint-metodissa piirtää drawImage:n avulla.
Ympyrän piirtämiseen fillArc:ia nopeampi metodi saattaisi olla drawOval, mutta en kuitenkaan ole 100% varma asiasta.
Unohtu lattaa tää sivu
http://koti.mbnet.fi/nordto/
Tökkiminen johtuu muuten siitä, että kun aika joka menee kuvan vaihtumiseen on kiinni osittain prosessorista ja
joka kerta kun lisää kiviä kestää vähän kauemmin kuin silloin kun ei lisätä kiviä
Pieni typo jäänyt koodiin: sekunttia, muuten ok.
Ihan kiva yksinkertainen peli.
lainaus:
Tökkiminen johtuu muuten siitä, että kun aika joka menee kuvan vaihtumiseen on kiinni osittain prosessorista ja
joka kerta kun lisää kiviä kestää vähän kauemmin kuin silloin kun ei lisätä kiviä
Tökkiminen taitaa muuten johtua siitä, että roskankerääjä käy lähes jatkuvasti. Paint metodissa oleva createImage varaa jatkuvasti tuhottomasti muistia, jota pitää sitten vapautella. Nykimisen saanee osittain pois luomalla kaksoispuskuroinnin tarvitseman kuvan kerran jossain alustus-metodissa ja käyttämällä samaa kuvaa jokaisella piirtokerralla.
hyvin kommentoitu!
No juu. Pitkästä aikaa näkee jonku joka sisentää tuolla paremmalla tyylilä. =)
EDIT: no joo... näyttäis et muutki Javalla ohjelmoijat sisentää tuohon tapaan.
toi aluksen väri muuten näkyy hieman huonosti tuota mustaa taustaa vasten...
Aihe on jo aika vanha, joten et voi enää vastata siihen.