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.