Willkommen auf unserem Seminar-Blog

Immer auf dem aktuellen Stand bleiben

Dieser Seminar-Blog befindet sich noch im Aufbau und wird in den kommenden Tagen entsprechend verfeinert.

Member Login

Lost your password?

Registration is closed

Sorry, you are not allowed to register by yourself on this site!

You must either be invited by one of our team member or request an invitation by email at viad.info {at} zhdk {dot} ch.

Lektion 10 – Endaufgabe: Circle Space Pong

4. Oktober 2012

Von den Physik-Libraries etwas enttäuscht, habe ich mich entschlossen, die "Physik", bzw. die Kollisionsabfragen für mein Spiel selber zu programmieren. Da ich viel Zeit verloren habe, musste ich mich etwas beeilen. Spielidee/Konzept Ich wollte das Spiel Pong verändern und die Spielfläche auf einen Kreis projezieren. Zwei Spieler müssen dafür sorgen, dass der Ball nie den Rand erreicht. In der Mitte wirkt eine Gravitationskraft dafür, dass der Ball abgelenkt wird und der Einschlagort schwer vorauszusehen ist. Die Gravitation wechselt zwischen anziehend und abstossend. Bedienungskonzept Die Idee wäre gewesen, dass das Spiel schlussendlich mit Kinect gespielt werden kann und die Paddles durch Kreisbewegung der Hand, bzw. Hände gesteuert werden kann. Zur Umsetzung bin ich leider nicht mehr gekommen. Entwicklung Den Grossteil der Zeit habe ich damit verbracht, den Ball physikalisch korrekt abprallen zu lassen und damit verbundene Fehler zu flicken. Ich hatte lange "Tunneling"-Effekte und der Ball verliess das Spielfeld. Erst durch das Zurückverschieben des Balles ins Spielfeld nach der Kollision (mit seeeehr viel Sinus-Kosinus-Kram!! 🙁 ) hats geklappt. Hier ein paar Beispiele der Prototypen: Endergebniss Für das Endspiel habe ich noch ein paar Hintergrundgrafiken erstellt, um das ganze grafisch noch etwas ansprechend zu gestalten. Aufgrund der Gravitation habe ich als Thema was Sternen-Starwars-Space-Mässiges gewählt. Leider bin ich nicht mehr dazu gekommen, das Spiel im Multiplayer-Modus umzusetzen und im Moment ist es einfach Singleplayer. (Survival-Mode) Hauptmenü Screen Game-Over Screen Hauptspiel mit anziehender Gravitation Projekt zum Download Download hier Codebeispiele Initialisierung von Spiel und Gravity

private void initGame() {
ball = new Ball(0,0, 25);
ball.set(new PVector(width/2, height/2+200), new PVector(random(-3,3),-1));

paddleLeft = new Paddle(20, 0, 360, 270, 30);

gravityDirection = 0;
if(gravityController != null) {
gravityController.quit();
}
gravityController = new TimeController(2000,6000,THREAD_MODE_GRAVITY_CONTROL);
gravityController.start();
gameStartTime = millis();
}

Auszug aus der Kollisionsabfrage

private void checkMovementAndGravity() {
PVector vDistFromCenter = PVector.sub(pos, centerPos);

float r = vDistFromCenter.mag();
float K = 2500.0;

if(gravityDirection < 0) {
K = 1800;
}

float a = K / sq(r);

PVector gravityVector = PVector.sub(centerPos,pos);
gravityVector.setMag(a);
gravityVector.mult(gravityDirection);

if(r > minGravityRadius && r < maxGravityRadius) {
dir.add(gravityVector);
}

if(r > 150 && dir.mag() > 20) {
dir.setMag(8);
}
pos.add(dir);

}

private void checkEdgeCollision() {
PVector vDistFromCenter = PVector.sub(pos, centerPos);

if(vDistFromCenter.mag() > gameCircleRadius-radius) {
if(checkCollision) {
speed = START_SPEED;
checkCollision = false;
checkPaddleCollisionBlocker = true;
paddleCollisionBlockTime = millis();
bounceOff(vDistFromCenter, gameCircleRadius);

stopGame();
}
} else {
checkCollision = true;
}
}

private void checkPaddleCollision() {
PVector vDistFromCenter = PVector.sub(pos, centerPos);
float ballAngleFromCenter = calculateBallAngleFromCenter(vDistFromCenter);

if(millis() - paddleCollisionBlockTime > 200) {
checkPaddleCollisionBlocker = false;
}

float paddleStart = paddleLeft.angle;

if(ballAngleFromCenter < radians(30)) {
paddleStart = paddleStart - radians(360);
}

float paddleEnd = paddleLeft.angle + radians(paddleLeft.lengthAngle);

if(vDistFromCenter.mag() > paddleRadius-radius) {

println("start " + degrees(paddleStart));
println("end " + degrees(paddleEnd));
println("degree " + degrees(ballAngleFromCenter) + "\n");
if(ballAngleFromCenter > paddleStart && ballAngleFromCenter < paddleEnd) {
if(checkPaddleCollision && !checkPaddleCollisionBlocker) {
bounceOff(vDistFromCenter, paddleRadius);
checkPaddleCollision = false;
speed += 0.2;

}
}
} else {
checkPaddleCollision = true;
}

}

private void bounceOff(PVector vDistFromCenter, float borderRadius) {
float entryAngle = PVector.angleBetween(dir,vDistFromCenter);

float bounceAngle = entryAngle * 2;

if(bounceAngle < radians(10)) {
bounceAngle = radians(15);
} else if(bounceAngle > radians(60)) {
bounceAngle = radians(50);
}

float Rgoal = borderRadius - radius;
float Rnow = vDistFromCenter.mag();
float part2 = (sq(Rnow) * sq(cos(entryAngle))) - sq(Rnow) + sq(Rgoal);
float offset = (Rnow * cos(entryAngle)) - sqrt(part2);
PVector correctionMove = dir.get();
correctionMove.setMag(offset);
correctionMove.mult(-1);
pos.add(correctionMove);

float orientierung = dir.x * vDistFromCenter.y - dir.y * vDistFromCenter.x;
rotate2D(dir,bounceAngle * (orientierung > 0 ? 1 : -1));

dir.x *=-1;
dir.y *=-1;
dir.setMag(speed);
}

private void rotate2D(PVector v, float theta) {
float m = v.mag();
float a = v.heading2D();

a += theta;

v.x = m * cos(a);
v.y = m * sin(a);
}

private float calculateBallAngleFromCenter(PVector vDistFromCenter) {
float ballAngleFromCenter = 0;
float ballAngle = PVector.angleBetween(vDistFromCenter,new PVector(1,0));
if(pos.y < height/2) {
ballAngleFromCenter = radians(360) - ballAngle;
} else {
ballAngleFromCenter = ballAngle;
}
return ballAngleFromCenter;
}

void draw() {
calcPos();

PVector vDistFromCenter = PVector.sub(pos, centerPos);
float drawAngle = PVector.angleBetween(dir,new PVector(0,-1));
pushMatrix();
translate(pos.x,pos.y);
fill(255);

image(backgroundImage,-50,-50);

popMatrix();
//drawDebugLines();

}