@slawaweis:
Hi ich könnte deinen Quellcode ziemlich gut gebrauchen !
wäre wirklich net, wenn du ihn posten könntest.
Danke!
OK, da ist es. Es sind zwei Klassen, wobei die zweite sehr viele Sachen enthält und man diese ruhig auf andere Dateien verteilen kann. Die beiden Dateien müssen im Package "rocketgame" abgelegt werden. Der Quelltext ist teilweise dokumentiert. Falls Du was nicht verstehst, schneide den Teil raus und poste den hier.
Ich übernehme keine Haftung für eventuelle Schäden die damit entstehen können! Es ist ein ungetestetes Programm, ein "Dirty Proof of Concept". Es läuft aber, jedenfalls bei mir.
Die Hilfsgrafiken sind aktiviert, dass sind die bunten Linien und Kreise. Rot steht für den Sichtpunkt der Rakete oder des Spielers, das ist der eigentliche Kollisionspunkt mit einer Barriere. Blau steht für die zentrale Linie des Tunnels. Grün ist der Vorderkreis, also die vordere Wand des Tunnels, die sollte man im fertigen Spiel nicht sehen.
Bis jetzt fliegt nur eine Barriere durch den Tunnel. Mehrere Barrieren, die Kollisionsberechnung und Spielabbruch, die Textur der Barrieren und das gesamte Interface fehlen. Die meisten Probleme bereiteten mir die Geschwindigkeiten, da muss man noch viel experimentieren.
[highlight="java"]
package rocketgame;
import java.awt.event.*;
import javax.swing.*;
public class RocketGameStart
{
public static void main(String [] args)
{
JFrame frame = new JFrame("Rocket Game");
frame.setSize(800, 800);
// frame.setResizable(false);
frame.setLocationRelativeTo(null);
// final TunnelPanel tp = new TunnelPanel(400);
final TunnelPanel tp = new TunnelPanel(1100);
tp.setHelpGraphicsEnabled(true);
frame.getContentPane().add(tp);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e)
{
tp.stopAnimation();
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run()
{
tp.startAnimation();
}
});
}
}
[/highlight]
[highlight="java"]
package rocketgame;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;
public class TunnelPanel extends JPanel
{
protected float tunnel_radius = 0;
protected float tunnel_diameter = 0;
/** diese Variable speichert den Center des vorderen Kreises (den grünen).
Diese Variable wird nach der Mausbewegung angepasst. */
protected Point2D.Float tunnel_front_center = new Point2D.Float(0f, 0f);
/** der graue Kreis */
protected MovementCircle movement_circle = null;
/** Eine Liste mit allen verfügbaren Barrieren */
protected ArrayList<AbstractBarrier> barrier_list = null;
/** die aktuell angezeigte Barriere */
protected AbstractBarrier current_barrier = null;
/** die Positionen der Seitenlinien auf dem Vorderkreis (den grünen) */
protected float [] tinnel_side_positions = {
360f*(1.0f/6.0f),
360f*(2.0f/6.0f),
360f*(3.0f/6.0f),
360f*(4.0f/6.0f),
360f*(5.0f/6.0f),
360f*(6.0f/6.0f)
};
protected Thread thread = null;
protected TunnelRunner tunnel_runner = null;
protected boolean help_graphics_enabled = false;
public TunnelPanel(float tunnel_radius)
{
super(null);
this.tunnel_radius = tunnel_radius;
this.tunnel_diameter = tunnel_radius*2;
this.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
this.addMouseMotionListener(new MouseController());
movement_circle = new MovementCircle();
barrier_list = new ArrayList<AbstractBarrier>();
barrier_list.add(new BigHoleBarrier());
barrier_list.add(new RectangleHoleBarrier());
// hier wird eine Barriere als aktive (die sichtbar ist) ausgewählt
current_barrier = barrier_list.get(0);
}
public boolean isHelpGraphicsEnabled()
{
return help_graphics_enabled;
}
public void setHelpGraphicsEnabled(boolean enabled)
{
this.help_graphics_enabled = enabled;
}
////////////////////////////////////////////////////////////////////////
// Paint
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Dimension size = getSize();
Graphics2D g2 = (Graphics2D)g;
g2.setBackground(Color.white);
g2.clearRect(0, 0, size.width, size.height);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.translate(size.width/2, size.height/2);
paintTunnelSideLines(g2, Color.black);
paintBarrier(g2, movement_circle);
paintBarrier(g2, current_barrier);
if(help_graphics_enabled)
paintHelpGraphics(g2);
}
// die nächsten zwei Funktionen zeichnen die Seitenlinien
protected void paintTunnelSideLines(Graphics2D g2, Color color)
{
g2.setColor(Color.black);
paintTunnelSideLine(g2, 0);
paintTunnelSideLine(g2, 1);
paintTunnelSideLine(g2, 2);
paintTunnelSideLine(g2, 3);
paintTunnelSideLine(g2, 4);
paintTunnelSideLine(g2, 5);
}
protected void paintTunnelSideLine(Graphics2D g2,
int side_line_index)
{
Point2D.Float poc = getPointOnCircle(tunnel_front_center,
tunnel_radius,
tinnel_side_positions[side_line_index]);
Line2D.Float base_line = new Line2D.Float(0f, 0f, poc.x, poc.y);
Point2D.Float tp1 = getPointOnLine(base_line, 0.02f);
Point2D.Float tp2 = getPointOnLine(base_line, 0.02f);
Path2D.Float path = new Path2D.Float();
path.moveTo(tp1.x, tp1.y);
path.lineTo(poc.x+tp2.y, poc.y-tp2.x);
path.lineTo(poc.x-tp2.y, poc.y+tp2.x);
path.closePath();
g2.fill(path);
}
// die nächste Funktion zeichnet eine Barriere
protected void paintBarrier(Graphics2D g2, AbstractBarrier barrier)
{
barrier.updateBarrierShapes();
if(barrier instanceof MovementCircle)
{
g2.setColor(Color.gray);
g2.draw(barrier.front);
}
else
{
g2.setColor(new Color(235, 235, 235));
g2.fill(barrier.back);
g2.setColor(Color.black);
g2.draw(barrier.back);
g2.setColor(Color.white);
g2.fill(barrier.front);
g2.setColor(Color.black);
g2.draw(barrier.front);
}
}
// die nächste Funktion zeichnet die Hilfsgrafiken
protected void paintHelpGraphics(Graphics2D g2)
{
g2.setColor(Color.green);
g2.drawOval((int)(-tunnel_radius+tunnel_front_center.x),
(int)(-tunnel_radius+tunnel_front_center.y),
(int)tunnel_diameter,
(int)tunnel_diameter);
g2.setColor(Color.blue);
g2.drawLine(0, 0, (int)tunnel_front_center.x,
(int)tunnel_front_center.y);
g2.setColor(Color.red);
g2.drawLine(-10, 0, 10, 0);
g2.drawLine(0, -10, 0, 10);
}
// Paint END
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// Animation & Interactivity
public synchronized void startAnimation()
{
if(thread == null)
{
tunnel_runner = new TunnelRunner();
thread = new Thread(tunnel_runner);
thread.start();
}
}
public synchronized void stopAnimation()
{
if(thread != null)
{
tunnel_runner.loop = false;
thread = null;
}
}
protected class TunnelRunner implements Runnable
{
protected boolean loop = true;
@Override
public void run()
{
// In dieser Schleife werden die Positionen und die Geschwindigkeiten
// der aktiven Elemente (Barriere, Seitenlinien) angepasst
while(loop)
{
// das ist der graue Kreis, der sich asymetrisch zu den Barieren bewegt
// und so ein Gefühl für Bewegung und Geschwindigkeit gibt
movement_circle.barrier_pos = (movement_circle.barrier_pos + 0.005f*(0.5f+movement_circle.barrier_pos*3f)) % 1f;
// hier wird die Position und die Geschwindigkeit eine Barriere angepasst
current_barrier.barrier_pos = (current_barrier.barrier_pos + 0.005f*(0.5f+current_barrier.barrier_pos*2.0f)) % 1f;
// die Seitenlinienpositionen auf dem Vorderkreis (den grünen) verschieben,
// um den Rotationseffekt zu erzeugen
float side_rotation_speed = 0.4f;
for(int i = 0; i < tinnel_side_positions.length; i++)
tinnel_side_positions
= (tinnel_side_positions + side_rotation_speed) % 360f;
repaint();
try { Thread.sleep(10); }
catch(InterruptedException e) { loop = false; e.printStackTrace(); }
}
}
}
protected class MouseController extends MouseAdapter
{
@Override
public void mouseMoved(MouseEvent e)
{
super.mouseMoved(e);
Dimension size = getSize();
// tunnel_center.setLocation(e.getX() - size.width/2, e.getY() - size.height/2);
tunnel_front_center.setLocation(-(e.getX() - size.width/2), -(e.getY() - size.height/2));
repaint();
}
}
// Animation & Interactivity END
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// Barriers
protected abstract class AbstractBarrier
{
/** Form, welche die Vorderseite eine Barriere darstellt */
protected Shape front = null;
/** Form, welche die Hinterseite eine Barriere darstellt */
protected Shape back = null;
/** Position im Tunnel zwischen 0f (Hinten) und 1f (Vorne).
Kann man auch als Tiefe ansehen */
protected float barrier_pos = 0f;
protected abstract void updateBarrierShapes();
}
protected class MovementCircle extends AbstractBarrier
{
@Override
protected void updateBarrierShapes()
{
// 2D Postion im Tunnel anhand der Tiefe ermitteln
Point2D.Float pit = getPointOnLine(0, 0,
tunnel_front_center.x,
tunnel_front_center.y,
barrier_pos);
float barrier_radius = barrier_pos*tunnel_radius;
front = new Ellipse2D.Float(-barrier_radius+pit.x, -barrier_radius+pit.y,
barrier_radius*2, barrier_radius*2);
}
}
protected class BigHoleBarrier extends AbstractBarrier
{
@Override
protected void updateBarrierShapes()
{
// 2D Postion im Tunnel anhand der Tiefe ermitteln
Point2D.Float pit = getPointOnLine(0, 0,
tunnel_front_center.x,
tunnel_front_center.y,
barrier_pos);
// Vorderform für die Barriere aufbauen
float barrier_radius = (barrier_pos*tunnel_radius);
float barrier_diameter = barrier_radius*2;
float hole_radius = barrier_radius*0.9f;
float hole_diameter = hole_radius*2;
Ellipse2D.Float barrier_base = null;
Ellipse2D.Float barrier_hole = null;
Area area = null;
barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
-barrier_radius+pit.y,
barrier_diameter,
barrier_diameter);
barrier_hole = new Ellipse2D.Float(-hole_radius+pit.x,
-hole_radius+pit.y,
hole_diameter,
hole_diameter);
area = new Area(barrier_base);
area.subtract(new Area(barrier_hole));
this.front = area;
// Hinterform für die Barriere aufbauen
barrier_radius = barrier_radius*0.96f;
barrier_diameter = barrier_radius*2;
hole_radius = barrier_radius*0.9f;
hole_diameter = hole_radius*2;
barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
-barrier_radius+pit.y,
barrier_diameter,
barrier_diameter);
barrier_hole = new Ellipse2D.Float(-hole_radius+pit.x,
-hole_radius+pit.y,
hole_diameter,
hole_diameter);
area = new Area(barrier_base);
area.subtract(new Area(barrier_hole));
this.back = area;
}
}
protected class RectangleHoleBarrier extends AbstractBarrier
{
@Override
protected void updateBarrierShapes()
{
// 2D Postion im Tunnel anhand der Tiefe ermitteln
Point2D.Float pit = getPointOnLine(0, 0,
tunnel_front_center.x,
tunnel_front_center.y,
barrier_pos);
// Vorderform für die Barriere aufbauen
float barrier_radius = (barrier_pos*tunnel_radius);
float barrier_diameter = barrier_radius*2;
float hole_width = barrier_radius*0.7f;
float hole_height = barrier_radius*0.2f;
Ellipse2D.Float barrier_base = null;
Rectangle2D.Float barrier_hole = null;
Area area = null;
barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
-barrier_radius+pit.y,
barrier_diameter,
barrier_diameter);
barrier_hole = new Rectangle2D.Float(-hole_width+pit.x,
-hole_height+pit.y,
hole_width*2,
hole_height*2);
area = new Area(barrier_base);
area.subtract(new Area(barrier_hole));
this.front = area;
// Hinterform für die Barriere aufbauen
barrier_radius = barrier_radius*0.96f;
barrier_diameter = barrier_radius*2;
hole_width = barrier_radius*0.7f;
hole_height = barrier_radius*0.2f;
barrier_base = new Ellipse2D.Float(-barrier_radius+pit.x,
-barrier_radius+pit.y,
barrier_diameter,
barrier_diameter);
barrier_hole = new Rectangle2D.Float(-hole_width+pit.x,
-hole_height+pit.y,
hole_width*2,
hole_height*2);
area = new Area(barrier_base);
area.subtract(new Area(barrier_hole));
this.back = area;
}
}
// Barriers END
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// Geometric Help Functions
protected static Point2D.Float getPointOnCircle(Point2D.Float center,
float radius, float angle)
{
return getPointOnCircle(center.x, center.y, radius, angle);
}
protected static Point2D.Float getPointOnCircle(float x, float y,
float radius, float angle)
{
return new Point2D.Float(x + (float)(radius*Math.cos(Math.toRadians(angle))),
y + (float)(radius*Math.sin(Math.toRadians(angle))));
}
public static Point2D.Float getPointOnLine(Line2D.Float line,
float t)
{
return getPointOnLine(line.x1, line.y1, line.x2, line.y2, t);
}
public static Point2D.Float getPointOnLine(float x1, float y1,
float x2, float y2,
float t)
{
return new Point2D.Float((x2 - x1)*t + x1,
(y2 - y1)*t + y1);
}
// Geometric Help Functions END
////////////////////////////////////////////////////////////////////////
}
[/highlight]
Slawa