Hier finden Sie die Quellcodes und benötigten Grafiken zum Geschicklichkeitsspiel „Lunar Lander“ aus dem Buch (Kapitel 3.3), damit Sie den langen Code nicht von Hand abtippen müssen.

Video des Gameplays:


Verwendete Grafiken: Download

Quellcode:

#import <UIKit/UIKit.h>
#import <CoreMotion/CoreMotion.h>
#import <QuartzCore/QuartzCore.h>

@interface lunarlanderViewController : UIViewController {
  // Hintergrund
  UIImageView *canvas;
  // Raumgleiter
  UIImageView *ship;
  UIImageView *blast;
  double shipSpeedX;
  double shipSpeedY;
  int leadfoot; // 1 = Vollgas

  // Zielort (Design)
  UIImageView *station;
  // Zielort Landeplattform
  UIImageView *platform;

  // Head-up-Display
  UIImageView *hud; 
  UIImageView *hud_oxygen;
  UIImageView *hud_petrol;
  UILabel *hud_level;

  int level; // aktueller Level
  double oxygen; // verbleibender Sauerstoff
  double petrol; // verbleibender Treibstoff
    
  // Array mit Landschaftsdaten
  NSMutableArray *areaDesign;

  CMMotionManager *motionManager;

  bool normalAction; // NO = nicht bewegen
}

@property (nonatomic,strong) UIImageView *canvas;
@property (nonatomic,strong) UIImageView *ship;
@property (nonatomic, strong) UIImageView *blast;
@property (nonatomic, strong) UIImageView *station;
@property (nonatomic, strong) UIImageView *platform;
@property (nonatomic, strong) UIImageView *hud;
@property (nonatomic, strong) UIImageView *hud_oxygen;
@property (nonatomic, strong) UIImageView *hud_petrol;
@property (nonatomic, strong) UILabel *hud_level;
@property (nonatomic, strong) NSMutableArray *areaDesign;
@property (nonatomic, strong) CMMotionManager *motionManager;

- (void)restartLevel;
- (void)reduceOxygen;
- (void)missionFailed;
- (void)missionAccomplished;
- (void)gameEngine;

@end
#import "lunarlanderViewController.h"
#include "leveldesign.h"

#define maxLevel 7

@implementation lunarlanderViewController
@synthesize canvas, ship, blast, station, platform,
hud, hud_level, hud_oxygen, hud_petrol, areaDesign; 
@synthesize  motionManager;

-(void) restartLevel {
  
  // beendet Explonsanimation, falls failed
  [ship stopAnimating];
  ship.alpha = 1.0;
  blast.alpha = 1.0;
  
  // Gelaendeteile positionieren
  for (int i = 0; i < [areaDesign count]; i++) {
    UIImage *tempImg = [UIImage alloc];
    UIImageView *area = [areaDesign objectAtIndex:i];
    if (areaW[level][i] ==1) tempImg = [UIImage imageNamed:@"area_50x50.png"];
    if (areaW[level][i] ==2) tempImg = [UIImage imageNamed:@"area_130x130.png"];
    area.frame = CGRectMake(0,0, tempImg.size.width, tempImg.size.height);
    [area setImage:tempImg];
    area.center = CGPointMake(areaX[level][i], areaY[level][i]);
  }
  
  station.frame = CGRectMake(stationX[level], stationY[level],140,60);
  platform.frame = CGRectMake(stationX[level]+37, stationY[level]+53,68,7);

  ship.center = CGPointMake(shipX[level], shipY[level]);
  ship.transform = CGAffineTransformMakeRotation(0);
  shipSpeedX = 0;
  shipSpeedY = -0.1;
  leadfoot = 0;
  oxygen = 100;
  petrol = 100;
  normalAction = YES;
}

// zieht jede Sekunde 1 Zaehler vom Sauerstoff ab
-(void) reduceOxygen {
  if (oxygen>0) oxygen--;
}

- (void)loadView {
  
  // Statusleiste entfernen und Hintergrundbeleuchtung ein
  [[UIApplication sharedApplication] setStatusBarHidden:YES];  
  [[UIApplication sharedApplication] setIdleTimerDisabled:YES];
  
  level = 0;
  
  // Hintergrundbild initialisieren
  canvas = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen]
                                               applicationFrame]];
  canvas.image = [UIImage imageNamed:@"canvas.png"];
  canvas.userInteractionEnabled = YES;
  self.view = canvas;
  
  // Felslandschaft initialisieren
  areaDesign = [[NSMutableArray alloc] init];
  for (int i = 0; i < sizeof(areaX[level])/sizeof(areaX[level][0]); i++) {
    UIImageView *area = [[UIImageView alloc]
                               initWithFrame:CGRectMake(0,0,50,50)];
    [areaDesign addObject:area];
    [canvas addSubview:area];
  }
  
  // Design der Landeplattform initialisieren
  station = [[UIImageView alloc] initWithFrame:CGRectMake(stationX[level],
                                                          stationY[level],
                                                          140, 60)];
  station.animationImages = [NSArray arrayWithObjects:
                 [UIImage imageNamed:@"station0.png"],
                 [UIImage imageNamed:@"station.png"],
                 [UIImage imageNamed:@"station1.png"],
                 [UIImage imageNamed:@"station.png"],
                 nil];
  station.animationDuration = 0.5;
  station.animationRepeatCount = 0;
  [station startAnimating];
  [canvas addSubview:station];

  // Landeplattform initialisieren
  platform = [[UIImageView alloc] initWithFrame:CGRectMake(stationX[level]+37,
                                                           stationY[level]+53,
                                                           68, 7)];
  platform.image = [UIImage imageNamed:@"platform.png"];
  [canvas addSubview:platform];
  
  
  // Duesenanimation initialisieren
  blast = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 35, 12)];
  blast.animationImages = [NSArray arrayWithObjects:
                 [UIImage imageNamed:@"fireblast0.png"],
                 [UIImage imageNamed:@"fireblast1.png"],
                 [UIImage imageNamed:@"fireblast2.png"],
                 nil];
  blast.animationDuration = 0.1;
  blast.animationRepeatCount = 0;
  blast.hidden = YES;
  [blast startAnimating];
  [canvas addSubview:blast];
  
  // Raumgleiter initialisieren
  ship = [[UIImageView alloc] initWithFrame:CGRectMake(shipX[level],
                                                       shipY[level],
                                                       47, 43)];
  ship.image = [UIImage imageNamed:@"ship.png"];
  // Explosionsanimation hinzufuegen
  ship.animationImages = [NSArray arrayWithObjects:
              [UIImage imageNamed:@"explosion0.png"],
              [UIImage imageNamed:@"explosion1.png"],
              [UIImage imageNamed:@"explosion2.png"],
              nil];
  ship.animationDuration = 0.3;
  ship.animationRepeatCount = 0;
  [canvas addSubview:ship];
  
  // Head-Up-Information initialisieren
  hud_level = [[UILabel alloc] initWithFrame:CGRectMake(0, 1, 19, 30)];
  hud_level.backgroundColor = [UIColor clearColor];
  hud_level.text = @"";
  hud_level.textAlignment = UITextAlignmentRight;
  hud_level.font = [UIFont fontWithName:@"Helvetica" size: 22.0];
  hud_level.textColor = [UIColor whiteColor];
  [canvas addSubview:hud_level];

  hud_oxygen = [[UIImageView alloc] initWithFrame:CGRectMake(30, 9, 50, 5)];
  hud_oxygen.backgroundColor = [UIColor colorWithRed:0 green:0.75
                                                blue:1 alpha:1];
  [canvas addSubview:hud_oxygen];

  hud_petrol = [[UIImageView alloc] initWithFrame:CGRectMake(30, 19, 50, 5)];
  hud_petrol.backgroundColor = [UIColor colorWithRed:0.75 green:0.5
                                              blue:0.75 alpha:1];
  [canvas addSubview:hud_petrol];
  
  hud = [[UIImageView alloc] initWithFrame:CGRectMake(21, 7, 61, 19)];
  hud.image = [UIImage imageNamed:@"hud.png"];
  [canvas addSubview:hud];
  
  
  // automatischen Countdown als Timer einrichten
  [NSTimer scheduledTimerWithTimeInterval:0.3
                                   target: self
                                 selector:@selector(reduceOxygen)
                                 userInfo:nil
                                  repeats:YES];
  
  // Accelerometer initialisieren
  motionManager = [[CMMotionManager alloc] init];
  motionManager.accelerometerUpdateInterval = 0.060;
  [motionManager startAccelerometerUpdates];
  
  // Level generieren
  [self restartLevel];
  
  // gameEngine als Intervall starten
  CADisplayLink *callGameEngine = [CADisplayLink
                                   displayLinkWithTarget:self 
                                   selector:@selector(gameEngine)];
  [callGameEngine setFrameInterval:2];
  [callGameEngine addToRunLoop:[NSRunLoop currentRunLoop]
                       forMode:NSDefaultRunLoopMode];
  
}

-(void) missionFailed {
  // keine Interaktion mehr
  normalAction = NO;
  // Explosionsanimation starten
  [ship startAnimating];
  // Fallen und Rotieren animieren
  [UIView transitionWithView:self.view
                    duration:2.0
                     options:UIViewAnimationOptionCurveEaseIn animations:^{
    ship.center = CGPointMake(ship.center.x, 520);
    ship.alpha = 0.0;
    ship.transform = CGAffineTransformMakeRotation(3.14);
  } completion:nil];
  // Level Neustart
  [self performSelector:@selector(restartLevel) withObject:nil afterDelay:2.5];
}

-(void) missionAccomplished {
  // Unsichtbar werden
  [UIView transitionWithView:self.view
                    duration:2.0
                     options:UIViewAnimationOptionCurveEaseIn animations:^{
    normalAction = NO;
    ship.alpha = 0.0;
    blast.alpha = 0.0;
  } completion:^(BOOL finished) {
    // naechster Level (wenn hoechster Level, dann von vorne)
    level = (level+1) % maxLevel;
    [self restartLevel];  
  }];
}

-(void) gameEngine {
  
  // nur durchfuehren, wenn gerade keine Explosion oder Landung
  if (normalAction) {
    
    // Head-Up-Display
    hud_level.text = [NSString stringWithFormat:@"%d", level+1];
    hud_oxygen.frame = CGRectMake(30, 9, oxygen/2, 5);
    hud_petrol.frame = CGRectMake(30, 19, petrol/2, 5);

    // seitliche Steuerung ueber Accelerometer
    CMAccelerometerData *acceleration = motionManager.accelerometerData;
    shipSpeedX += acceleration.acceleration.x/15;
      
    // Schwerkraft
    if (normalAction) shipSpeedY += 0.015;
    
    // Spieler gibt Gas
    if ((leadfoot == 1) && (petrol>0)) shipSpeedY -= 0.05;
  
    // Kollision mit Spielfeldrand -> abprallen
    if ( (ship.center.x+shipSpeedX>320) || (ship.center.x+shipSpeedX<0) ) {
      shipSpeedX = -shipSpeedX/2;
    }
    
    // Kollision mit Boden -> Explosion
    if (ship.center.y+shipSpeedY>440) [self missionFailed];
  
    // Kollision mit Gelaende -> Explosion
    for(int i = 0; i < [areaDesign count]; i++) {
      UIImageView *area = [areaDesign objectAtIndex:i];
      if ( // Pythagoras zur Abstandsmessung
          (area.center.x-ship.center.x) * (area.center.x-ship.center.x)+
          (area.center.y-ship.center.y) * (area.center.y-ship.center.y)<
          (area.bounds.size.width/2 + 20) * (area.bounds.size.width/2 + 20))
        [self missionFailed];
    }
  
    // Landung bei langsamer Geschwindigkeit? -> naechster Level!  
    if (CGRectIntersectsRect(ship.frame, platform.frame)) {
      if ((shipSpeedX>-0.8) &&
          (shipSpeedX<0.8) &&
          (shipSpeedY<0.8) &&
          (shipSpeedY >= 0)) {
        [self missionAccomplished];  
      }
      // sonst -> Explosion
      else [self missionFailed];
    }

    // Countdown vorbei? -> Explosion
    if (oxygen == 0) [self missionFailed];

    // Raumschiff darstellen
    ship.center = CGPointMake(ship.center.x+shipSpeedX,
                              ship.center.y+shipSpeedY);
    
    // Duesen darstellen, wenn Spieler Gas gibt
    if ((leadfoot == 1) & (petrol>0)) {
      petrol -= 0.25;
      blast.center = CGPointMake(ship.center.x, ship.center.y+26);
      blast.hidden = NO;
    }
    else blast.hidden = YES;
  }  
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
  leadfoot = 1;
}

-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
  leadfoot = 0;
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

- (void)viewDidUnload {
}

@end
extern int areaX[7][14];
extern int areaY[7][14];
extern int areaW[7][14];
extern int stationX[7];
extern int stationY[7];
extern int shipX[7];
extern int shipY[7];

@interface leveldesign : NSObject {}
@end
#import "leveldesign.h"

int areaX[7][14]={
	{66,292,48,315,197,348,273,-43,90,323,3,245,30,318},
	{268,310,14,248,51,268,56,345,28,310,260,303,6,36},
	{11,253,47,261,120,308,265,109,2,53,269,304,-3,327},
	{48,201,304,307,100,97,10,197,278,28,108,41,305,256},
	{168,125,308,13,244,154,78,287,110,183,35,42,67,304},
	{110,40,108,253,215,114,281,55,183,136,138,-12,117,318},
	{208,236,-3,169,158,136,131,-26,276,305,26,-42,200,275}
};
int areaY[7][14]={
	{389,199,356,229,446,93,426,293,454,163,339,465,453,464},
	{373,37,110,252,347,164,250,390,410,224,314,100,288,174},
	{139,216,347,251,233,181,355,302,288,198,421,242,398,321},
	{181,323,127,374,269,444,319,28,51,433,195,256,259,326},
	{449,15,183,248,252,374,139,283,410,-11,174,430,221,247},
	{85,420,122,165,-8,232,-20,480,325,263,36,400,194,203},
	{137,359,315,150,250,247,281,449,403,211,132,364,405,154}
};

int areaW[7][14]={
	{1,1,1,1,1,1,1,2,2,2,2,2,2,2},
	{1,1,1,1,1,1,1,2,2,2,2,2,2,2},
	{1,1,1,1,1,1,1,2,2,2,2,2,2,2},
	{1,1,1,1,1,1,1,2,2,2,2,2,2,2},
	{1,1,1,1,1,1,1,2,2,2,2,2,2,2},
	{1,1,1,1,1,1,1,2,2,2,2,2,2,2},
	{1,1,1,1,1,1,1,2,2,2,2,2,2,2}
};

int stationX[7]={199,180,50,110,-16,208,174};
int stationY[7]={348,398,398,398,57,87,281};

int shipX[7]={100,50,50,50,264,40,190};
int shipY[7]={50,50,50,50,376,60,45};

@implementation leveldesign

@end

Einen Kommentar schreiben

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.