Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: Java: Avaruuspeli

Sivun loppuun

TJN [03.03.2005 16:52:36]

#

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;
	}
}

tsuriga [05.03.2005 00:14:41]

#

Ei kannata käyttää samaa nimeä metodille ja muuttujalle samanaikaisesti. Ihan mukava idea, vähä tökittää.

sooda [05.03.2005 08:06:46]

#

Oiskohan binääriä?

Sami [05.03.2005 11:34:44]

#

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/Asteroid.html

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.

TJN [05.03.2005 11:44:34]

#

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ä

Jaska [05.03.2005 12:31:29]

#

Pieni typo jäänyt koodiin: sekunttia, muuten ok.

FooBat [08.03.2005 11:40:02]

#

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.

Vesis [18.03.2005 19:03:12]

#

hyvin kommentoitu!

Tomppu [26.06.2005 16:32:21]

#

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.

Tommittaja [04.04.2009 13:59:25]

#

toi aluksen väri muuten näkyy hieman huonosti tuota mustaa taustaa vasten...


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta