Android App Pure Pong!


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!

3 Kommentare

  1. Pingback: Processing – Über dieses Weblog « processing – tutorial

  2. Pingback: Processing Apps für Android X – Erstellen einer .apk-Datei aus .pde « processing – tutorial

  3. Mad Mike

    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…

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Log Out / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Log Out / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Log Out / Ändern )

Verbinde mit %s

Follow

Bekomme jeden neuen Artikel in deinen Posteingang.

Join 25 other followers