Permalänk

[Java] extremt enkelt spel

Hallå
Jag började rätt nyligen med att programmera och då i java. Jag följer en bok och försöker nu göra ett slags spel. Till att börja med vill jag få en blå cirkel att röra sig beroende på hur jag trycker på piltangenterna. Jag har skrivit så att om cirkeln nuddar kanten sänks dess hastighet till 0. Problemet är att när jag startar programmet så rör sig inte cirkeln, den står helt still, och mina tryck på piltangenterna hjälper inte.

Jag programmerar i netbeans

Här är källkoden

Citat:

package spel1;

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class KeyApp3 extends Applet implements Runnable,
KeyListener{
int RADIE=20;
double bilx=200, bily=200;
double vx=0, vy=0;
boolean leftDown= false, rightDown= false, up= false, down= false;

public void init(){
addKeyListener( this);
requestFocus();
}

public void paint( Graphics g)
{
g.setColor( Color.blue);
g.fillOval( (int)(bilx-RADIE), (int)(bily-RADIE), 2*RADIE, 2*RADIE);
}

public void start()
{
Thread ny= new Thread( this);
ny.start();
}
public void run()
{
if(bilx+RADIE > WIDTH)
vx= 0;
if(bilx-RADIE<0)
vx= 0;
if(bily+RADIE > WIDTH)
vy= 0;
if(bily-RADIE<0)
vy=0;

while( true){
if(leftDown) vx= vx- 0.05;
if(rightDown) vx= vx+ 0.05;
if(up) vy= vy+ 0.05;
if(down) vy= vy- 0.05;

repaint();

try{ Thread.sleep( 10);} catch( InterruptedException ie){}
}
}
public void keyPressed(KeyEvent ke) {
if( ke.getKeyCode() == KeyEvent.VK_LEFT) leftDown= true;
if( ke.getKeyCode() == KeyEvent.VK_RIGHT) rightDown= true;
if( ke.getKeyCode() == KeyEvent.VK_UP) up= true;
if( ke.getKeyCode() == KeyEvent.VK_DOWN) rightDown= true;
}

public void keyReleased(KeyEvent ke) {
if( ke.getKeyCode() == KeyEvent.VK_LEFT) leftDown= false;
if( ke.getKeyCode() == KeyEvent.VK_RIGHT) rightDown= false;
if( ke.getKeyCode() == KeyEvent.VK_UP) up= false;
if( ke.getKeyCode() == KeyEvent.VK_DOWN) rightDown= false;
}

public void keyTyped(KeyEvent e) {}

}

Permalänk
Medlem

Du ändrar bara på dina v variabler i loopen men sen använder du inte dom i paint metoden. Hur skulle den kunna röra sig alls.

Permalänk
Medlem

Precis som Racy säger måste du ändra cirkelns koordinater.

Lägg till det här innan repaint() så ska du se att det fungerar:
bilx = bilx + vx;
bily = bily + vy;
Den kommer däremot röra sig konstigt för du har skrivit att rightDown ska vara true, och inte down, när du trycker på nedåtpil. Jag kan rekomendera bättre namn på dom för att förhindra den typen av problem.

I övrigt kan jag se problem med kollisionsdetekteringen, men det kanske du vill lösa det själv.

Permalänk

ok, tack så jättemycket, försöker

Permalänk

Känner mig grymt trög nu, det här är min nya källkod, men funkar inte. Ändrade det du sa dawe91. Tack för hjälpen btw.

Edit: Kollisionsdetekteringen kommer sen, mitt första mål är att kunna röra bollen med piltangenterna. Jag kan inte hitta felet tyvärr.

package spel1; import java.applet.*; import java.awt.*; import java.awt.event.*; public class KeyApp3 extends Applet implements Runnable, KeyListener{ int RADIE=20; double bilx=100, bily=100; double vx=0, vy=0; boolean leftDown= false, rightDown= false, up= false, down= false; public void init(){ addKeyListener( this); requestFocus(); } public void paint( Graphics g) { g.setColor( Color.blue); g.fillOval( (int)(bilx-RADIE), (int)(bily-RADIE), 2*RADIE, 2*RADIE); } public void start() { Thread ny= new Thread( this); ny.start(); } public void run() { if(bilx+RADIE > WIDTH) vx= 0; if(bilx-RADIE<0) vx= 0; if(bily+RADIE > WIDTH) vy= 0; if(bily-RADIE<0) vy=0; while( true){ if(leftDown) vx= vx- 0.05; if(rightDown) vx= vx+ 0.05; if(up) vy= vy+ 0.05; if(down) vy= vy- 0.05; bilx= bilx+ vx; bily= bily+ vy; repaint(); try{ Thread.sleep( 10);} catch( InterruptedException ie){} } } public void keyPressed(KeyEvent ke) { if( ke.getKeyCode() == KeyEvent.VK_LEFT) leftDown= true; if( ke.getKeyCode() == KeyEvent.VK_RIGHT) rightDown= true; if( ke.getKeyCode() == KeyEvent.VK_UP) up= true; if( ke.getKeyCode() == KeyEvent.VK_DOWN) down= true; } public void keyReleased(KeyEvent ke) { if( ke.getKeyCode() == KeyEvent.VK_LEFT) leftDown= false; if( ke.getKeyCode() == KeyEvent.VK_RIGHT) rightDown= false; if( ke.getKeyCode() == KeyEvent.VK_UP) up= false; if( ke.getKeyCode() == KeyEvent.VK_DOWN) down= false; } public void keyTyped(KeyEvent e) {} }

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av digitaldigital
Känner mig grymt trög nu, det här är min nya källkod, men funkar inte. Ändrade det du sa dawe91. Tack för hjälpen btw.

Edit: Kollisionsdetekteringen kommer sen, mitt första mål är att kunna röra bollen med piltangenterna. Jag kan inte hitta felet tyvärr.

Det funkar för mig.
Några grejer dock:
Bollen rör sig snabbare om man trycker flera gånger på samma piltangent.
Upp och ner knapparna är speglade så när man trycker på upp så åker bollen ner osv.

Visa signatur

I'm Winston Wolfe. I solve problems.

Permalänk

Men vah? Kör du i netbeans 6.8? För mig funkar det inte alls ... =(

Permalänk
Medlem

Funkar fint för mig med. Jag har NetBeans 6.7.1
Tänk på att du måste klicka i rutan också eftersom det inte finns någon auto-focus

Permalänk

aha nu fungerar det, tack. Vill tacka alla så jättemycket för hjälpen. Nu ska jag försöka lösa kollisionen :).
Varför flimmrar bollen?, det har jag inte sagt åt den att göra ..

Edit: Grymt svårt att fixa kollisionen. Har prövat att skriva om så att om bilx överstiger 100 så blir bilx=100, men det fungerar inte, kan jag kanske ha satt hela " if bilx+RADIE>Width " på fel ställe?
vx= 0

Permalänk
Hedersmedlem
Citat:

Ursprungligen inskrivet av digitaldigital
aha nu fungerar det, tack. Vill tacka alla så jättemycket för hjälpen. Nu ska jag försöka lösa kollisionen :).
En fråga bara, varför flimmrar bollen?, det har jag inte sagt åt den att göra ..

Utan att ens ha tittat på koden så gissar jag på att du ritar ut direkt på ytan som visas i fönstret. Det man brukar göra är att använda sig av dubbel buffering.

Visa signatur

Forumregler | Feedbackforumet | Något som behöver modereras? Tryck på Anmäl inlägget och ge en anledning, någon moderator kommer granska inlägget och göra (egen) bedömning
"Fate. Protects fools, little children and ships named Enterprise." - Riker - ST:TNG

Permalänk
Medlem

Paint-metoden ritar på en bild som sedan visas på skärmen. När bilden sedan ska uppdateras suddas bilden och därefter ritas bilden om. Om bilden då skickas för att visas på skärmen när datorn precis har suddat kommer det bli vitt. Detta gör att bilden flimrar.

Detta är inte så svårt att fixa. Om du i stället har två bilder, en där du ritar och en som du visar, kan du kopiera rit-bilden till visningsbilden precis innan du suddar. Då visas aldrig en vit bild

Skriv:
VolatileImage bgi;
i början där du deklarerar dina variabler

Sen lägger du till det här någon stans i din class(förslagsvis efter paint-metoden):

public void update(Graphics g) { if (bgi == null) { bgi = createVolatileImage(1600, 1200); this.requestFocus(); } bgi.getGraphics().clearRect(0, 0, 1600, 1200); paint(bgi.getGraphics()); g.drawImage(bgi, 0, 0, this); }

Nu borde det inte flimra mer

Permalänk
Hedersmedlem

Jag tog mig friheten att piffa upp några inlägg med code-taggar.

Citat:

Ursprungligen inskrivet av digitaldigital
[...]
Edit: Grymt svårt att fixa kollisionen. Har prövat att skriva om så att om bilx överstiger 100 så blir bilx=100, men det fungerar inte, kan jag kanske ha satt hela " if bilx+RADIE>Width " på fel ställe?
vx= 0

Ja du ska ha det inuti loopen annars kontrolleras det aldrig mer än en gång.

Visa signatur

Forumregler | Feedbackforumet | Något som behöver modereras? Tryck på Anmäl inlägget och ge en anledning, någon moderator kommer granska inlägget och göra (egen) bedömning
"Fate. Protects fools, little children and ships named Enterprise." - Riker - ST:TNG

Permalänk

ok Aqualize, prövar det.

Dawe, e den strängen ngt som alltid fungerar i de flesta program (som en nybörjare kommer göra) eller fungerar det bara under vissa omständigheter?

Edit: Tack Dawe. Aqualize, jag placerar den i while(true) men då står bollen stilla hela tiden. Det känns som att bilx+RADIE alltid är mer än WIDTH, men bilx+RADIE=100+20=120. Så hur bestämmer jag ett värde på WIDTH?

Permalänk
Medlem

Den borde alltid fungera. Finns kanske bättre sätt att lösa det när man ska göra mer avancerade saker. Jag har iaf alltid använt den när jag gjort något som är runnable och har aldrig fått problem.

Permalänk

ok, skitbra, fungerar felfritt just nu iaf xD

Som jag skrev över, jag har stött på mer problem; jag tror jag måste sätta ett värde på WIDTH typ, men hur?

Permalänk
Medlem

Till att börja med måste du deklarera den. Tycker det är konstigt att den inte säger nått om det. Där du skrivit "double bilx = ..." bla, skriver du int WIDTH = 200(tex). Du borde även ha en HEIGHT eftersom man kanske inte vill att dimensionen ska vara samma horisontellt och vågrätt.
Om du vill att dessa värden ska vara samma som fönsterstorleken kan du skriva HEIGHT = getHeight(); och WIDTH = getWidth(); i while-loopen, men du måste som sagt deklarera dessa först.

Permalänk

Tack, funkar skitbra! Ni e awesome

Permalänk

Nytt problem .. Jag har lagt till ett hinder som ska avsluta spelet när du träffar det. Problemet är att hindret spawnar ibland mitt på mitt hinder eller mitt på mig, försökte avhjälpa det med

if(bilx<hinderx)
if(bilx+50>hinderx)
if(bily<hindery)
if(bily+50>hindery){
hinderx= RADIE+(1200-2*RADIE)*Math.random();
hindery= RADIE+(400-2*RADIE)*Math.random();}
if(bilx<hinderx)
if(bilx+50>hinderx)
if(bily>hindery)
if(bily-50<hindery){
hinderx= RADIE+(1200-2*RADIE)*Math.random();
hindery= RADIE+(400-2*RADIE)*Math.random();}
if(bilx>hinderx)
if(bilx-50<hinderx)
if(bily<hindery)
if(bily+50>hindery){
hinderx= RADIE+(1200-2*RADIE)*Math.random();
hindery= RADIE+(400-2*RADIE)*Math.random();}
if(bilx>hinderx+RADIEF)
if(bilx-50<hinderx+RADIEF)
if(bily>hindery+RADIEF)
if(bily-50<hindery+RADIEF){
hinderx= RADIE+(1200-2*RADIE)*Math.random();
hindery= RADIE+(400-2*RADIE)*Math.random();}
//------------------------------------------------------------------------------
if(targetx<hinderx)
if(targetx+50>hinderx)
if(targety<hindery)
if(targety+50>hindery){
hinderx= RADIE+(1200-2*RADIE)*Math.random();
hindery= RADIE+(400-2*RADIE)*Math.random();}
if(targetx<hinderx)
if(targetx+50>hinderx)
if(targety>hindery)
if(targety-50<hindery){
hinderx= RADIE+(1200-2*RADIE)*Math.random();
hindery= RADIE+(400-2*RADIE)*Math.random();}
if(targetx>hinderx)
if(targetx-50<hinderx)
if(targety<hindery)
if(targety+50>hindery){
hinderx= RADIE+(1200-2*RADIE)*Math.random();
hindery= RADIE+(400-2*RADIE)*Math.random();}
if(targetx>hinderx+RADIEF)
if(targetx-50<hinderx+RADIEF)
if(targety>hindery+RADIEF)
if(targety-50<hindery+RADIEF){
hinderx= RADIE+(1200-2*RADIE)*Math.random();
hindery= RADIE+(400-2*RADIE)*Math.random();}

}

Något som inte hjälpte tyvärr. Linkar hela min källkod också,

package spel1;

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.VolatileImage;

public class KeyApp3 extends Applet implements Runnable,
KeyListener{
int DEATH= 1;
double hinderx= 600, hindery=325;
int RADIEF= 40;
int points= 0;
double targetx=200, targety=200;
VolatileImage bgi;
int WIDTH= 1210;
int HEIGHT= 760;
int RADIE=20;
double bilx=100, bily=100;
double vx=0, vy=0;
boolean leftDown= false, rightDown= false, up= false, down= false;

public void init(){
addKeyListener( this);
requestFocus();
}

public void paint( Graphics g)
{
g.drawRect(10,10,1200,750);
g.setColor( Color.gray);
g.fillRect(11,11,1199,749);
g.setColor( Color.black);
g.fillOval((int)hinderx-RADIEF,(int)hindery-RADIEF, 2*RADIEF, 2*RADIEF);
g.setColor( Color.red);
g.fillOval( (int)targetx-RADIE, (int)targety-RADIE, 2*RADIE, 2*RADIE);
g.setColor( Color.blue);
g.fillOval( (int)(bilx-RADIE), (int)(bily-RADIE), 2*RADIE, 2*RADIE);
if( DEATH==1338){
g.setColor( Color.black);
g.fillRect(10,10, 1200,750);
g.setColor( Color.red);
g.drawString( "YOU FAIL, bara "+points+" poäng. Better luck next time", 400,300);
}
}
public void update(Graphics g) {
if (bgi == null) {
bgi = createVolatileImage(1600, 1200);
this.requestFocus();
}
bgi.getGraphics().clearRect(0, 0, 1600, 1200);
paint(bgi.getGraphics());
g.drawImage(bgi, 0, 0, this);
}

public void start()
{
Thread ny= new Thread( this);
ny.start();
}
public void run()
{

while( true){
double dx= targetx- bilx;
double dy= targety- bily;
double distSqr= dx*dx+dy*dy;
if( distSqr< (RADIE+RADIE)*(RADIE+RADIE)){
targetx= RADIE+(1200-2*RADIE)*Math.random();
targety= RADIE+(400-2*RADIE)*Math.random();
points= points+1;
showStatus(points+" poäng");
RADIEF= RADIEF+5;
hinderx= RADIE+(1200-2*RADIE)*Math.random();
hindery= RADIE+(400-2*RADIE)*Math.random();
if(bilx<hinderx)
if(bilx+50>hinderx)
if(bily<hindery)
if(bily+50>hindery){
hinderx= RADIE+(1200-2*RADIE)*Math.random();
hindery= RADIE+(400-2*RADIE)*Math.random();}
if(bilx<hinderx)
if(bilx+50>hinderx)
if(bily>hindery)
if(bily-50<hindery){
hinderx= RADIE+(1200-2*RADIE)*Math.random();
hindery= RADIE+(400-2*RADIE)*Math.random();}
if(bilx>hinderx)
if(bilx-50<hinderx)
if(bily<hindery)
if(bily+50>hindery){
hinderx= RADIE+(1200-2*RADIE)*Math.random();
hindery= RADIE+(400-2*RADIE)*Math.random();}
if(bilx>hinderx+RADIEF)
if(bilx-50<hinderx+RADIEF)
if(bily>hindery+RADIEF)
if(bily-50<hindery+RADIEF){
hinderx= RADIE+(1200-2*RADIE)*Math.random();
hindery= RADIE+(400-2*RADIE)*Math.random();}
//------------------------------------------------------------------------------
if(targetx<hinderx)
if(targetx+50>hinderx)
if(targety<hindery)
if(targety+50>hindery){
hinderx= RADIE+(1200-2*RADIE)*Math.random();
hindery= RADIE+(400-2*RADIE)*Math.random();}
if(targetx<hinderx)
if(targetx+50>hinderx)
if(targety>hindery)
if(targety-50<hindery){
hinderx= RADIE+(1200-2*RADIE)*Math.random();
hindery= RADIE+(400-2*RADIE)*Math.random();}
if(targetx>hinderx)
if(targetx-50<hinderx)
if(targety<hindery)
if(targety+50>hindery){
hinderx= RADIE+(1200-2*RADIE)*Math.random();
hindery= RADIE+(400-2*RADIE)*Math.random();}
if(targetx>hinderx+RADIEF)
if(targetx-50<hinderx+RADIEF)
if(targety>hindery+RADIEF)
if(targety-50<hindery+RADIEF){
hinderx= RADIE+(1200-2*RADIE)*Math.random();
hindery= RADIE+(400-2*RADIE)*Math.random();}

}
double fx= hinderx-bilx;
double fy= hindery-bily;
double fdiag= (fx*fx)+(fy*fy);
if( fdiag< (RADIEF+RADIE)*(RADIEF+RADIE)){
vx=0;
vy=0;
DEATH= 1338;
}

if(leftDown) vx= vx- 0.05;
if(rightDown) vx= vx+ 0.05;
if(up) vy= vy- 0.05;
if(down) vy= vy+ 0.05;

if(bilx+RADIE >= WIDTH)
vx= 0.5*-vx-0.5;
if(bilx-RADIE<=10)
vx= 0.5*-vx+0.5;
if(bily+RADIE >= HEIGHT)
vy= 0.5*-vy-0.5;
if(bily-RADIE<=10)
vy= 0.5*-vy+0.5;

bilx= bilx+ vx;
bily= bily+ vy;
repaint();

try{ Thread.sleep( 10);} catch( InterruptedException ie){}
}
}
public void keyPressed(KeyEvent ke) {
if( ke.getKeyCode() == KeyEvent.VK_LEFT) leftDown= true;
if( ke.getKeyCode() == KeyEvent.VK_RIGHT) rightDown= true;
if( ke.getKeyCode() == KeyEvent.VK_UP) up= true;
if( ke.getKeyCode() == KeyEvent.VK_DOWN) down= true;
}

public void keyReleased(KeyEvent ke) {
if( ke.getKeyCode() == KeyEvent.VK_LEFT) leftDown= false;
if( ke.getKeyCode() == KeyEvent.VK_RIGHT) rightDown= false;
if( ke.getKeyCode() == KeyEvent.VK_UP) up= false;
if( ke.getKeyCode() == KeyEvent.VK_DOWN) down= false;
}

public void keyTyped(KeyEvent e) {}

}

Skulle bli glad om någon visste vad jag gjorde för fel. Hindret ska ju respawna om det spawnar på mig eller målet, men det vill sig inte

Permalänk
Medlem

if(bilx<hinderx)
if(bilx+50>hinderx)
if(bily<hindery)
if(bily+50>hindery){ ...

De tre första if-satserna här gör ingen skillnad. Du måste skriva vad som ska hända antingen på samma rad eller i klamrar. Använd i stället && (och) och || (eller) i if-satserna för att få med flera villkor - tex if (bilx < hinderx && bily z hindery || bilx+50 > hindery && bilx...). Kanske ska vara ett par parenteser där i också. Du kan även använda "else if" för att göra koden snabbare. Om radat upp if-satser där den första är en vanlig if och de senare är else if hoppar den förbi de resterade else if om den hittar en if-sats som är sann.

Hur som helst måste detta måste gå att göra på något mycket bättre och enklare sätt men jag har har inte tid att fixa det nu.

Permalänk
Medlem

skillnad blir det väl? det lbir väl typ

if(bilx<hinderx) if(bilx+50>hinderx) if(bily<hindery) if(bily+50>hindery) { //koden }

så brukar det väl vara i språk iaf har inte programmerat java riktigt.

sen föreslår jag att du gör en funktion som kollar hitbox.
typ

public bool checkCollision( double firstObjectX, double firstObjectY, double firstObjectWidth, double firstObjectHeight, double secondObjectX, double secondObjectY, double secondObjectWidth, double secondObjectHeight) { if (kollisionskoll) return true; return false; }

typ, så kan du loopa tills de inte kolliderar lättare

do { someCode } while(checkCollision(tjohooooo));

eller något sånt

Visa signatur

Laptop - MacBook 2.0GHz, 4GB ram, Intel GMA 950
Stationär - i5 3570k @ 4ghz, 8gb ram, 120gb ssd + 2tb hdd, Windows 8 64bit, fractal design arc
Citera så jag hittar tillbaka :)

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av E_maN
skillnad blir det väl? det lbir väl typ

if(bilx<hinderx) if(bilx+50>hinderx) if(bily<hindery) if(bily+50>hindery) { //koden }

Nej, du måste ha klamrar.

if(bilx<hinderx) { if(bilx+50>hinderx) { if(bily<hindery) { if(bily+50>hindery) { //koden } } } }

Och då kan man lika gärna skriva med || i en if-sats och få samma resultat.

Permalänk
Medlem

hmm skummt, så i java kan man inte skriva typ?

if (1 > 0) i++;

fast jo det är klart blir ju mycket snyggare med && istället.

Visa signatur

Laptop - MacBook 2.0GHz, 4GB ram, Intel GMA 950
Stationär - i5 3570k @ 4ghz, 8gb ram, 120gb ssd + 2tb hdd, Windows 8 64bit, fractal design arc
Citera så jag hittar tillbaka :)

Permalänk
Medlem

Jag testade nu och det kunde man visst
Det beror väl antagligen på att den isf inte avslutar "raden" förrän den kommer till ett semikolon.