Guten Tag,
Ich habe die Aufgabe bekommen ein Netzwerk für ein SpielProjekt zu erstellen in der Uni. Dabei handelt es sich um ein Pongspiel welches mit Javafx geschrieben wurde. Dabei haben wir alle Klassen im MVC-Prinzip eingeteilt.
Auch habe ich schon einen (Chat)Server geschrieben/frankenstein'd/ aus anderen Beispielen zusammengebastelt der auf eine Nachricht von einem Client wartet und diese dann anschließend an alle anderen Clients schickt
Jetzt zum eigentlichen Problem:
Ich bekomme es einfach nicht das Spiel mit sowohl Server als auch Client zu verbinden. Mein Ansatz den ich gerade hätte wäre dieser:
Der Client (beinhaltet nur Keylistener und den View) schickt bei einem Tastendruck eine Nachricht an den Server.
Dieser wiederum hat Kontrolle über den Rest des Controllers und der Modelklasse und führt alle Berechnungen durch. Danach schickt er wieder alle relevanten Informationen ( Positionen der Schläger und des Balles) wieder zu einem "Clientthread" zurück der dann wiederum auf die lokale Modelklassen schreibt. Schlussendlich liest der Client wieder von der dieser lokalen Modelklasse zurück und stellt alles auf der Timeline dar.
Davor habe ich schon versucht meinen gesamten Controller in den Client hineinzupacken, jedoch war dann das Spielfenster gefreezed als der Client sich verbunden hatte.
Ist diese Einteilung von Aufgaben sinnvoll und wie bekomme ich es zum Beispiel hin einen KeyListener in den Client zu implementieren. Da habe ich zur Zeit die meisten Probleme..
Javacode:
Controller:
Server:
Client:
Ich probiere es jetzt mal aus den Controller im größten Teil einfach so zu lassen, jedoch bei den KeyEventlistener Methoden ausführen zu lassen die im Client stehen und die wiederum Nachrichten an den Server schicken.
Grüße Minti
Ich habe die Aufgabe bekommen ein Netzwerk für ein SpielProjekt zu erstellen in der Uni. Dabei handelt es sich um ein Pongspiel welches mit Javafx geschrieben wurde. Dabei haben wir alle Klassen im MVC-Prinzip eingeteilt.
Auch habe ich schon einen (Chat)Server geschrieben/frankenstein'd/ aus anderen Beispielen zusammengebastelt der auf eine Nachricht von einem Client wartet und diese dann anschließend an alle anderen Clients schickt
Jetzt zum eigentlichen Problem:
Ich bekomme es einfach nicht das Spiel mit sowohl Server als auch Client zu verbinden. Mein Ansatz den ich gerade hätte wäre dieser:
Der Client (beinhaltet nur Keylistener und den View) schickt bei einem Tastendruck eine Nachricht an den Server.
Dieser wiederum hat Kontrolle über den Rest des Controllers und der Modelklasse und führt alle Berechnungen durch. Danach schickt er wieder alle relevanten Informationen ( Positionen der Schläger und des Balles) wieder zu einem "Clientthread" zurück der dann wiederum auf die lokale Modelklassen schreibt. Schlussendlich liest der Client wieder von der dieser lokalen Modelklasse zurück und stellt alles auf der Timeline dar.
Davor habe ich schon versucht meinen gesamten Controller in den Client hineinzupacken, jedoch war dann das Spielfenster gefreezed als der Client sich verbunden hatte.
Ist diese Einteilung von Aufgaben sinnvoll und wie bekomme ich es zum Beispiel hin einen KeyListener in den Client zu implementieren. Da habe ich zur Zeit die meisten Probleme..
Javacode:
Controller:
Java:
package controller;
import view.LocalMultiView;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.util.Duration;
import javafx.geometry.Bounds;
import model.Player;
import model.ScreenModel;
public class LocalMultiController
{
// private model.RacketModel racketModel;
// private model.BallModel ballModel;
private ScreenModel model;
private view.LocalMultiView view;
private Integer i = 0;
private Player life1;
private Player life2;
public LocalMultiController (ScreenModel model)
{
// this.racketModel = new RacketModel();
// this.ballModel = new BallModel();
this.view = new LocalMultiView();
this.model = model;
this.life1 = new Player(3);
this.life2 = new Player(3);
addEvent();
}
public void show ()
{
view.show(model.getStage());
}
public void addEvent ()
{
final Circle ball = view.getBall();
final Rectangle schlaeger1 = view.getRacket1().getRacket();
final Rectangle schlaeger2 = view.getRacket2().getRacket();
Scene scene = view.getPlayScene();
final Pane canvas = view.getPane();
/**
* Eventhandler für linken Schläger: S: runter, W: hoch
*/
scene.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>()
{
public void handle(KeyEvent ke)
{
double yPos1 = schlaeger1.getY();
if (ke.getCode() == KeyCode.S)
{
if ((yPos1 + schlaeger1.getHeight() + 20) > canvas.getBoundsInLocal().getMaxY())
{
yPos1 = canvas.getBoundsInLocal().getMaxY() - schlaeger1.getHeight();
}
else
{
yPos1 += 20;
}
schlaeger1.setY(yPos1);
}
else if (ke.getCode() == KeyCode.W)
{
if (yPos1 - 20 < 0)
{
yPos1 = 0;
}
else
{
yPos1 -= 20;
}
schlaeger1.setY(yPos1);
}
}
});
/**
* Eventhandler für rechten Schlaeger: Pfeil hoch: hoch, Pfeil runter: runter
*/
scene.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>()
{
public void handle(KeyEvent ke)
{
double yPos2 = schlaeger2.getY();
if (ke.getCode() == KeyCode.DOWN)
{
if ((yPos2 + schlaeger2.getHeight() + 20) > canvas.getBoundsInLocal().getMaxY())
{
yPos2 = canvas.getBoundsInLocal().getMaxY() - schlaeger2.getHeight();
}
else
{
yPos2 += 20;
}
schlaeger2.setY(yPos2);
}
else if (ke.getCode() == KeyCode.UP)
{
if (yPos2 - 20 < 0)
{
yPos2 = 0;
}
else
{
yPos2 -= 20;
}
schlaeger2.setY(yPos2);
}
}
});
/**
* Timeline mit unendlicher Wiederholung alle 20 Millisekunden
* für die Bewegung des Balls
*/
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(20),
new EventHandler<ActionEvent>()
{
double xPos = 3;
double yPos = 5;
@Override
public void handle(ActionEvent arg0)
{
/*
// Every 20 frames 10% faster
if (i++ % 50 == 0) {
xPos += (xPos<0 ? -1 : 1) * 0.5;
yPos += (yPos<0 ? -1 : 1) * 0.5;
}
*/
double oldX = ball.getLayoutX();
double schlaeger1CollisionX = schlaeger1.getX() + schlaeger1.getWidth();
double schlaeger2CollisionX = schlaeger2.getX();
ball.setLayoutX(ball.getLayoutX() + xPos);
ball.setLayoutY(ball.getLayoutY() + yPos);
Bounds bounds = canvas.getBoundsInLocal();
//Kollision unten
boolean boundBottom = ball.getLayoutY() >= (bounds
.getMaxY() - ball.getRadius());
//Kollision oben
boolean boundTop = (ball.getLayoutY() - ball.getRadius()) <= 0;
//Kollision rechts
boolean boundRight = ball.getLayoutX() >= (bounds
.getMaxX() - ball.getRadius());
//Kollision links
boolean boundLeft = (ball.getLayoutX() - ball.getRadius()) <= bounds.getMinX();
//Kollision Schlaeger
boolean boundSchlaeger1 = ball.getLayoutX() - ball.getRadius() <= schlaeger1CollisionX && oldX >= schlaeger1CollisionX && ball.getLayoutY() + ball.getRadius() >= schlaeger1.getY() && ball.getLayoutY() - ball.getRadius() <= schlaeger1.getY() + schlaeger1.getHeight() && xPos < 0;
boolean boundSchlaeger2 = ball.getLayoutX() + ball.getRadius() >= schlaeger2CollisionX && oldX <= schlaeger2CollisionX && ball.getLayoutY() + ball.getRadius() >= schlaeger2.getY() && ball.getLayoutY() - ball.getRadius() <= schlaeger2.getY() + schlaeger2.getHeight() && xPos > 0;
//Richtungswechsel
if (boundBottom || boundTop)
{
yPos *= -1;
}
//Abprallen
if (boundSchlaeger2 || boundSchlaeger1)
{
xPos *= -1;
}
if (boundLeft)
{
ball.relocate(20, 30);
xPos = 3;
yPos = 5;
life1.subLife();
System.out.println("Sp1: " + life1.getLife());
}
if (boundRight)
{
ball.relocate(20, 30);
xPos = 3;
yPos = 5;
life2.subLife();
System.out.println("Sp2: " + life2);
}
if (life1.getLife() == 0)
{
xPos = 0;
yPos = 0;
// To-Do Player2 hat gewonnen
//Try again
}
if (life2.getLife() == 0){
xPos = 0;
yPos = 0;
//To-Do Player1 hat gewonnen
//Try again
}
}
}));
// unendliche Anzahle an Wiederholungen
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
}
}
Server:
Java:
package net;
import java.io.*;
import java.net.*;
import java.util.*;
public class Server {
private ArrayList<ClientThread> ClientListe;
private int port;
private boolean Loopjanein;
public Server(int port) {
this.port = port;
ClientListe = new ArrayList<ClientThread>();
}
public void start() {
Loopjanein = true;
try
{
ServerSocket serverSocket = new ServerSocket(port);
while(Loopjanein)
{
// format message saying we are waiting
System.out.println("Server waiting for Clients on port " + port + ".");
Socket socket = serverSocket.accept();
if(!Loopjanein)
break;
ClientThread t = new ClientThread(socket);
ClientListe.add(t);
t.start();
}
try {
serverSocket.close();
}catch(Exception e) {}
} catch (IOException e) {
}
}
private void display(String msg) {
String yay = " " + msg;
System.out.println(yay);
}
private synchronized void allsenden(String message) { // broadcast
String Message = message + "\n";
System.out.print(Message);
for(int i = ClientListe.size(); --i >= 0;) {
ClientThread ClientT = ClientListe.get(i);
if(!ClientT.writeMsg(Message)) {
ClientListe.remove(i);
display("Disconnected Client " + ClientT.username + " removed from list.");
}
}
}
synchronized void rm(int id) {
for(int i = 0; i < ClientListe.size(); ++i) {
ClientThread ct = ClientListe.get(i);
if(ct.id == id) {
ClientListe.remove(i);
return;
}
}
}
public static void main(String[] args) {
int portNumber = 1500;
Server server = new Server(portNumber);
server.start();
}
/** One instance of this thread will run for each client */
public class ClientThread extends Thread {
Socket socket;
ObjectInputStream sInput;
ObjectOutputStream sOutput;
OutputStream OS;
int id;
String username;
ChatMessage cm;
ClientThread(Socket socket) {
this.socket = socket;
System.out.println("Thread trying to create Object Input/Output Streams");
try
{
sOutput = new ObjectOutputStream(socket.getOutputStream());
sInput = new ObjectInputStream(socket.getInputStream());
username = (String) sInput.readObject();
display(username + " just connected.");
}
catch (IOException e) {
display("Exception creating new Input/output Streams: " + e);
return;
}
catch (ClassNotFoundException e) {
}
}
public void run() {
boolean keepGoing = true;
while(keepGoing) {
try {
cm = (ChatMessage) sInput.readObject();
}
catch (IOException e) {
display(username + " Exception reading Streams: " + e);
break;
}
catch(ClassNotFoundException e2) {
break;
}
String message = cm.getMessage();
switch(cm.getType()) {
case ChatMessage.MESSAGE:
allsenden(username + ": " + message);
break;
case ChatMessage.LOGOUT:
display(username + " disconnected with a LOGOUT message.");
keepGoing = false;
break;
}
}
rm(id);
close();
}
private void close() {
try {if(sOutput != null) sOutput.close();}
catch(Exception e) {}
try {if(sInput != null) sInput.close();}
catch(Exception e) {};
try {if(socket != null) socket.close();}
catch (Exception e) {}
}
private boolean writeMsg(String msg) {
if(!socket.isConnected()) {
close();
return false;
}
try {
sOutput.writeObject(msg);
}
catch(IOException e) {
display("Error sending message to " + username);
display(e.toString());
}
return true;
}
}
}
Client:
Java:
package net;import java.net.*;
import java.io.*;
import java.util.*;
import model.ScreenModel;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.util.Duration;
public class Client {
private ObjectInputStream sInput;
private ObjectOutputStream sOutput;
private Socket socket;
private static ScreenModel model;
private static view.LocalMultiView view;
private static Integer i = 0;
private String server, username;
private int port;
public Client(String server, int port, String username) {
this.server = server;
this.port = port;
this.username = username;
}
public boolean start() {
try {
socket = new Socket(server, port);
}
catch(Exception ec) {
display("Error connectiong to server:" + ec);
return false;
}
String msg = "Connection accepted " + socket.getInetAddress() + ":" + socket.getPort();
display(msg);
try
{
sInput = new ObjectInputStream(socket.getInputStream());
sOutput = new ObjectOutputStream(socket.getOutputStream());
}
catch (IOException eIO) {
display("Exception creating new Input/output Streams: " + eIO);
return false;
}
new ListenFromServer().start();
try
{
sOutput.writeObject(username);
}
catch (IOException eIO) {
display("Exception doing login : " + eIO);
disconnect();
return false;
}
return true;
}
private void display(String msg) {
System.out.println(msg);
}
public void sendMessage(ChatMessage msg) {
try {
sOutput.writeObject(msg);
}
catch(IOException e) {
display("Exception writing to server: " + e);
}
}
private void disconnect() {
try {
if(sInput != null) sInput.close();
}
catch(Exception e) {}
try {
if(sOutput != null) sOutput.close();
}
catch(Exception e) {}
try{
if(socket != null) socket.close();
}
catch(Exception e) {}
}
public static void main(String[] args) {
int portNumber = 7777;
String serverAddress = "localhost";
String userName = "Anonymous";
switch(args.length) {
case 3:
serverAddress = args[2];
case 2:
try {
portNumber = Integer.parseInt(args[1]);
}
catch(Exception e) {
System.out.println("Invalid port number.");
System.out.println("Usage is: > java Client [username] [portNumber] [serverAddress]");
return;
}
case 1:
userName = args[0];
case 0:
break;
default:
System.out.println("Usage is: > java Client [username] [portNumber] {serverAddress]");
return;
}
Client client = new Client(serverAddress, portNumber, userName);
if(!client.start())
return;
Scanner scan = new Scanner(System.in);
while(true) { // waypoint
String msg = scan.nextLine();
if(msg.equalsIgnoreCase("LOGOUT")) {
client.sendMessage(new ChatMessage(ChatMessage.LOGOUT, ""));
break;
}
else if(msg.equalsIgnoreCase("WHOISIN")) {
client.sendMessage(new ChatMessage(ChatMessage.WHOISIN, ""));
}
else {
client.sendMessage(new ChatMessage(ChatMessage.MESSAGE, msg));
}
}
client.disconnect();
}
class ListenFromServer extends Thread {
public void run() {
while(true) {
try {
String msg = (String) sInput.readObject();
System.out.println(msg);
}
catch(IOException e) {
display("Server has close the connection: " + e);
break;
}
catch(ClassNotFoundException e2) {
}
}
}
}
}
Ich probiere es jetzt mal aus den Controller im größten Teil einfach so zu lassen, jedoch bei den KeyEventlistener Methoden ausführen zu lassen die im Client stehen und die wiederum Nachrichten an den Server schicken.
Grüße Minti