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