Mein erstes fertiges Projekt ist wieder mal Pong, diesmal Pure Pong!. Zum allgemeinen Verständnis siehe: Projekt Ping Pong. Die Version für Android ist eine schon recht deutlich veränderte.
- Ich habe im Gegensatz zu Ping Pong für die Steuerung des Balls und der Spielerbalken jetzt PVector-Objekte verwendet.
- Das Spiel nutzt Multitouch und ist ein reines Multiplayer-Game.
- Durch das Bewegen des Balkens während der Ballberührung kann man den Balls seitlich beschleunigen.
- Die Geschwindigkeit des Balls hängt von der Größe des Pointers während der Ballberührung ab. Er kann dadurch beschleunigt, oder gebremst werden.
- Es wurden Vibrations-Effekte für das haptisches Feedback eingebaut.
Hier meine purepong.apk zum Download (mit RechtsClick – Datei speichern unter)!!!
Geschafft: Game ist im Market unter: https://market.android.com/search?q=PurePong!
Hier der Quellcode mit Kommentaren:
// Imports
import android.content.Context;
import android.app.Notification;
import android.app.NotificationManager;
// Setup vibration globals:
NotificationManager gNotificationManager;
Notification gNotification;
long[] gVibrate = {
0, 100
};
// Globale Variablen
int size;
int s2;
int balls=5;
int balls1=5;
int serve=0;
int frame=0;
PVector ballPos;
PVector ballDir;
PVector playerPos;
PVector pplayerPos;
PVector playerDir;
PVector playerPos1;
PVector pplayerPos1;
PVector playerDir1;
float ballspeed;
float ballspeed1;
float maxSpeed;
float minSpeed;
float h24;
float h48;
float hh6;
float h6;
float h4;
float w8;
float w6;
int blockdir=0;
color bg = color(0, 150, 255);
color pl = color(255, 170, 0);
PFont font;
void setup()
{
size(screenWidth, screenHeight, A2D);
frameRate(30);
smooth();
//Damit sich die Ausrichtung des Displays nicht während des Spiels ändert
orientation(PORTRAIT);
maxSpeed=screenHeight/40;
minSpeed=screenHeight/200;
size=height/24;
//hier die am öftesten vorkommenden Berechnungen
s2=size/2;
h24=screenHeight/24;
h48=screenHeight/48;
hh6=screenHeight-screenHeight/6;
h6=screenHeight/6;
h4=screenHeight/4;
w8=screenWidth/8;
w6=screenWidth/6;
// die PVector-Objekte werden erzeugt
playerPos = new PVector(width/2, hh6);
pplayerPos = new PVector(playerPos.x, playerPos.y);
playerPos1 = new PVector(width/2, h6);
pplayerPos1 = new PVector(playerPos1.x, playerPos1.y);
ballPos = new PVector(width/2, height-h4);
ballDir = new PVector (0, -4);
textAlign(CENTER);
rectMode(CENTER);
font = createFont("Arial", 12);
stroke(180);
// Create our Notification Manager:
gNotificationManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
// Create our Notification that will do the vibration:
gNotification = new Notification();
// Set the vibration:
gNotification.vibrate = gVibrate;
}
void draw()
{
background(bg);
fill(180);
// für die Start-Einblendung
if (frameCount<120) {
translate(width/2, height/2);
textSize(w8);
rotate(PI/2);
text("PURE PONG!", 0, 0);
rotate(-PI/2);
translate(-width/2, -height/2);
}
else { // hier läuft das Spiel
line(0, height/2, width, height/2);
//Zeichnet verbleibende Bälle für die Spieler
for (int i=1; i<=balls1; i++) {
ellipse(width/(balls1+1)*i, height/3, h48, h48);
}
for (int i=1; i<=balls; i++) {
ellipse(width/(balls+1)*i, height*2/3, h48, h48);
}
// wenn ein Spieler gewonnen hat
if (balls<=0 || balls1 <=0) {
textSize(w8);
translate(width/2, height/2);
if (balls>balls1) {
text("YOU WON !", 0, h4);
}
else {
rotate(PI);
text("YOU WON !", 0, h4);
rotate(-PI);
}
translate(-width/2, -height/2);
}
else {
// Bewegung des Balles
ballPos.add(ballDir);
//Begrenzung seitlich
if (ballPos.x < 0+s2 || ballPos.x > width-s2) {
ballDir.x *= -1;
}
// Begrenzung Spieler 1 und Fehler
// Ball ist im Bereich des Balkens
if ( int(ballPos.y) >= int(hh6-h48-s2)) {
//Ball ist vor dem Balken
if ((ballPos.x > playerPos.x-w6 && ballPos.x < playerPos.x+w6)
&& blockdir>4) {
//Beschleunigung oder Verzögerung des Ball je nach Druckpunkt
ballDir.y *=-lerp(0.6, 3, ballspeed);
//Maximal und Minimalwerte für die Ballgeschwindigkeit
if (ballDir.y>0) {
ballDir.y=min(ballDir.y, maxSpeed);
ballDir.y=max(ballDir.y, minSpeed);
}
else {
ballDir.y=max(ballDir.y, -maxSpeed);
ballDir.y=min(ballDir.y, -minSpeed);
}
// Damit kann man dem Ball "Schnitt" verleihen
ballDir.x -=(pplayerPos.x-playerPos.x)/3;
//Haptisches Feedback wenn der Ball getroffen wird
gNotificationManager.notify(1, gNotification);
//Damit verhindert wird, dass der Ball mehrmals die Richtung wechselt
blockdir=0;
}
//bei Fehler
else {
balls-=1;
serve=0;
frame=0;
ballDir.y *=-1;
}
}
// Begrenzung Spieler 1 und Fehler
// Ball ist im Bereich des Balkens
if ( int(ballPos.y) <= int(h6+h48+s2)) {
//Ball ist vor dem Balken
if ((ballPos.x > playerPos1.x-w6 && ballPos.x < playerPos1.x+w6)
&& blockdir>4) {
//Beschleunigung oder Verzögerung des Ball je nach Druckpunkt
ballDir.y *=-lerp(0.6, 3, ballspeed1);
//Maximal und Minimalwerte für die Ballgeschwindigkeit
if (ballDir.y>0) {
ballDir.y=min(ballDir.y, maxSpeed);
ballDir.y=max(ballDir.y, minSpeed);
}
else {
ballDir.y=max(ballDir.y, -maxSpeed);
ballDir.y=min(ballDir.y, -minSpeed);
}
// Damit kann man dem Ball "Schnitt" verleihen
ballDir.x -=(pplayerPos1.x-playerPos1.x)/3;
//Haptisches Feedback wenn der Ball getroffen wird
gNotificationManager.notify(1, gNotification);
//Damit verhindert wird, dass der Ball mehrmals die Richtung wechselt
blockdir=0;
}
//bei Fehler
else {
balls1-=1;
serve=1;
frame=0;
ballDir.y *=-1;
}
}
// Zeichnet den Ball
stroke(255);
fill(255);
ellipse(ballPos.x, ballPos.y, size, size);
//Zeichnet die Balken
stroke(pl);
strokeWeight(h24);
line(playerPos.x-w8, hh6, playerPos.x+w8, hh6);
line(playerPos1.x-w8, h6, playerPos1.x+w8, h6);
strokeWeight(0);
stroke(200);
// Bewegung Player 1 und 2
pplayerPos.x=playerPos.x;
pplayerPos1.x=playerPos1.x;
}
// Spielverzögerung bei Fehler
if (serve==0 && frame<60) {
ballDir.x=0;
ballPos.x=playerPos.x;
ballPos.y=height-h4;
}
if (serve==1 && frame<60) {
ballPos.x=playerPos1.x;
ballPos.y=h4;
ballDir.x=0;
}
// Verzögerung bei Fehler
frame++;
// Blockierung der Ballrichtung nach dem Rückprall am Balken
blockdir++;
}
}
//Funktion für Multitouch Events von
// Eric Pavey - www.akeric.com - 2010-10-24 (verändert)
//-----------------------------------------------------------------------------------------
// Override Processing's surfaceTouchEvent, which will intercept all
// screen touch events. This code only runs when the screen is touched.
public boolean surfaceTouchEvent(MotionEvent me) {
// Zuordnung der TouchPoints zum jeweiligen Spieler
if (int(me.getY(0))<height/2) {
playerPos.x=me.getX(1);
playerPos1.x=me.getX(0);
ballspeed = me.getSize(1);
ballspeed1= me.getSize(0);
}
else {
playerPos.x=me.getX(0);
playerPos1.x=me.getX(1);
ballspeed = me.getSize(0);
ballspeed1= me.getSize(1);
}
return super.surfaceTouchEvent(me);
}
Viel Spass!
Pingback: Processing – Über dieses Weblog « processing – tutorial
Pingback: Processing Apps für Android X – Erstellen einer .apk-Datei aus .pde « processing – tutorial
Vielen Dank für’s Teilen, ich wollte schon immer eine solide Code-Grundlage für ein Breakout für Android haben. Ist das wirklich nur so wenig Code? Das ist ja Wahnsinn! Dachte da kommen jetzt 1000LoC oder sowas…