SlideShare a Scribd company logo
1 of 74
Download to read offline
Sprite Kit - Case Study
Michael Pan
For what
Storybook!
2D game
Storybook
https://www.youtube.com/watch?v=r_3TJtK1PjU
About Game
2D - Corona!
3D - Unity
What we will build
http://www.raywenderlich.com/42699/spritekit-tutorial-for-beginners
Create a Sprite Kit Project
Shooter
Make it landscape only
Run the project
Download the resource
http://cdn3.raywenderlich.com/wp-content/uploads/2015/01/
SpriteKitSimpleGameResources.zip
Drag resource into project
MyScene.m
#import "MyScene.h"!
!
@interface MyScene ()!
@property (nonatomic) SKSpriteNode * player;!
@end!
!
@implementation MyScene!
!
-(id)initWithSize:(CGSize)size { !
if (self = [super initWithSize:size]) {!
!
NSLog(@"Size: %@", NSStringFromCGSize(size));!
!
self.backgroundColor = [SKColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];!
self.player = [SKSpriteNode spriteNodeWithImageNamed:@"player"];!
self.player.position = CGPointMake(100, 100);!
[self addChild:self.player];!
}!
return self;!
}!
@end
Run
Check the log
??
why
http://stackoverflow.com/questions/9539676/uiviewcontroller-returns-invalid-
frame
Modify the ViewController.m
- (void)viewDidLoad!
{!
[super viewDidLoad];!
!
// Configure the view.!
SKView * skView = (SKView *)self.view;!
skView.showsFPS = YES;!
skView.showsNodeCount = YES;!
!
// Create and configure the scene.!
SKScene * scene = [MyScene sceneWithSize:skView.bounds.size];!
scene.scaleMode = SKSceneScaleModeAspectFill;!
!
// Present the scene.!
[skView presentScene:scene];!
}
viewDidAppear
-(void) viewDidAppear:(BOOL)animated{!
[super viewDidAppear:animated];!
SKView * skView = (SKView *)self.view;!
!
skView.showsFPS = YES;!
skView.showsNodeCount = YES;!
!
// Create and configure the scene.!
SKScene * scene = [MyScene sceneWithSize:skView.bounds.size];!
scene.scaleMode = SKSceneScaleModeAspectFill;!
!
// Present the scene.!
[skView presentScene:scene];!
}
Good result
What we learned
SKScene
SKSpriteNode
self.player = [SKSpriteNode spriteNodeWithImageNamed:@"player"];!
self.player.position = CGPointMake(100, 100);!
[self addChild:self.player];
Class relationship
SKNode
SKEffectNode
SKScene
SKSpriteNode
- (void)addChild:(SKNode *)node;
Position
SKScene
(0,0)
(100,100)
Put SpriteNode on scene - right-down??
SKScene
(0,0)
(100,100)
Put SpriteNode on scene - left-up ??
SKScene
(0,0)
(100,100)
Put SpriteNode on scene - center ??
SKScene
(0,0)
(100,100)
Anchor point
(0,0) (1,0)
(0,1) (1,1)
(0.5,0.5) default
Test - position (0,0) with default Anchor Point
self.player = [SKSpriteNode spriteNodeWithImageNamed:@"player"];!
self.player.position = CGPointMake(0, 0);!
[self addChild:self.player];
Test - position (0,0) with default Anchor Point(0,0)
self.player = [SKSpriteNode spriteNodeWithImageNamed:@"player"];!
self.player.position = CGPointMake(0, 0);!
self.player.anchorPoint = CGPointMake(0, 0);!
[self addChild:self.player];
Add enemy in MyScene.m (1)
- (void)addMonster {!
// Create sprite!
SKSpriteNode * monster = [SKSpriteNode
spriteNodeWithImageNamed:@"monster"];!
 !
// Determine where to spawn the monster along the Y axis!
int minY = monster.size.height / 2;!
int maxY = self.frame.size.height - monster.size.height / 2;!
int rangeY = maxY - minY;!
int actualY = (arc4random() % rangeY) + minY;!
!
monster.position = CGPointMake(self.frame.size.width +
monster.size.width/2, actualY);!
[self addChild:monster];!
}
Add enemy in MyScene.m (2)
- (void)addMonster {!
 !
//…!
// Determine speed of the monster!
int minDuration = 2.0;!
int maxDuration = 4.0;!
int rangeDuration = maxDuration - minDuration;!
int actualDuration = (arc4random() % rangeDuration) + minDuration;!
 !
// Create the actions!
SKAction * actionMove = [SKAction moveTo:CGPointMake(-monster.size.width/2,
actualY) duration:actualDuration];!
SKAction * actionMoveDone = [SKAction removeFromParent];!
[monster runAction:[SKAction sequence:@[actionMove, actionMoveDone]]];!
 !
}
What we learned
SKAction!
moveTo:duration:!
removeFromParent!
sequence:
Class view
NSObject
SKNode
SKSpriteNode
SKAction
- (void)runAction:(SKAction *)action;
UIResponder
- (void)update:(NSTimeInterval)currentTime
every 1/60 second will be called automatically
Stabilise the time interval
@interface MyScene ()!
@property (nonatomic) SKSpriteNode * player;!
@property (nonatomic) NSTimeInterval lastSpawnTimeInterval;!
@property (nonatomic) NSTimeInterval lastUpdateTimeInterval;!
@end
Codes in update:
- (void)update:(NSTimeInterval)currentTime {!
CFTimeInterval timeSinceLast = currentTime -
self.lastUpdateTimeInterval;!
self.lastUpdateTimeInterval = currentTime;!
if (timeSinceLast > 1) {!
timeSinceLast = 1.0 / 60.0;!
self.lastUpdateTimeInterval = currentTime;!
}!
[self updateWithTimeSinceLastUpdate:timeSinceLast];!
!
}
Every second add a enemy
- (void)updateWithTimeSinceLastUpdate:
(CFTimeInterval)timeSinceLast {!
 !
self.lastSpawnTimeInterval += timeSinceLast;!
if (self.lastSpawnTimeInterval > 1) {!
self.lastSpawnTimeInterval = 0;!
[self addMonster];!
}!
}!
Run the app
Throw projectile
touch
Throw projectile - vector
(spriteX, spriteY)
offsetX
offsetY (touchX, touchY)
offsetX = touchX - spriteX
offsetY = touchY - spriteY
Define helper function - offset
CGPoint subPoint(CGPoint a, CGPoint b ){!
CGPoint subPoint = CGPointMake(a.x - b.x, a.y - b.y);!
return subPoint;!
}
Unit value of vector
offsetX = touchX - spriteX
offsetY = touchY - spriteY
unitValue = sqrt(offsetX^2 + offsetY^2)
Normalised vector = (offsetX / unitValue , offsetY / unitValue)
offsetX
offsetY
unitValue
Define helper function - normalised offset
CGPoint normalisedPoint(CGPoint offset){!
CGFloat nValue = sqrtf(offset.x*offset.x + offset.y*offset.y);!
CGPoint nPoint = CGPointMake(offset.x/nValue, offset.y/nValue);!
return nPoint;!
}
Get touch event - add projectile
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{!
!
UITouch * touch = [touches anyObject];!
!
// get the location in the scene!
CGPoint location = [touch locationInNode:self] ;!
!
SKSpriteNode * projectile = [SKSpriteNode spriteNodeWithImageNamed:@"projectile"];!
projectile.position = self.player.position;!
!
CGPoint offset = subPoint(location, projectile.position);!
!
if (offset.x <= 0) return;!
!
[self addChild:projectile];!
}
Multiply vector - helper function
CGPoint multiplyVector(CGPoint vector, CGFloat amount){!
CGPoint newVec = CGPointMake(vector.x*amount, vector.y*amount);!
return newVec;!
}
Calculate projectile destination
(offsetX, offsetY)
(offsetX/unitValue, offsetY/unitValue)
newVec = multiplyVector(offset, 1000)
(player.x+newVec.x, player.y+newVec.y)
Add point with offset
CGPoint addOffset(CGPoint a, CGPoint offset){!
CGPoint newVec = CGPointMake(a.x+offset.x, a.y+offset.y);!
return newVec;!
}
Get touch event - cal projectile destination
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{!
! // !
! CGPoint direction = normalisedPoint(offset);!
!
!
! CGPoint shootOffset = multiplyVector(direction, 1000);!
!
! CGPoint realDest = addOffset(projectile.position, shootOffset);!
!
! float velocity = 480.0/1.0;!
! float realMoveDuration = self.size.width / velocity;!
! SKAction * actionMove = [SKAction moveTo:realDest duration:realMoveDuration];!
! SKAction * actionMoveDone = [SKAction removeFromParent];!
! [projectile runAction:[SKAction sequence:@[actionMove, actionMoveDone]]];!
}
Run
Rotate the projectile
float velocity = 480.0/1.0;!
float realMoveDuration = self.size.width / velocity;!
SKAction * actionMove = [SKAction moveTo:realDest
duration:realMoveDuration];!
SKAction * actionMoveDone = [SKAction removeFromParent];!
SKAction * sequence = [SKAction sequence:@[actionMove,
actionMoveDone]];!
!
SKAction * rotate = [SKAction rotateByAngle:4*M_PI duration:0.5];!
SKAction * forever = [SKAction repeatActionForever:rotate];!
SKAction * group = [SKAction group:@[forever,sequence]];!
[projectile runAction:group];
Run
Collision Detection
Use the power of Physic Engine
Set gravity!
!
Set contact delegate
self.physicsWorld.gravity = CGVectorMake(0,0);
self.physicsWorld.contactDelegate = self;
@interface MyScene ()<SKPhysicsContactDelegate>!
@property (nonatomic) SKSpriteNode * player;!
@property (nonatomic) NSTimeInterval lastSpawnTimeInterval;!
@property (nonatomic) NSTimeInterval lastUpdateTimeInterval;!
@end
SKPhysicsContactDelegate
physicsWorld
@interface SKScene : SKEffectNode!
!
@property (SK_NONATOMIC_IOSONLY, readonly) SKPhysicsWorld *physicsWorld;!
!
@end
physicsBody
monster body!
!
projectile body
monster.physicsBody = [SKPhysicsBody
bodyWithRectangleOfSize:monster.size];
projectile.physicsBody = [SKPhysicsBody
bodyWithCircleOfRadius:projectile.size.width/2];
physics attributes
// movable!
monster.physicsBody.dynamic = YES;!
!
// like ID!
monster.physicsBody.categoryBitMask = monsterCategory;!
!
// which ID will be contact!
monster.physicsBody.contactTestBitMask = projectileCategory;!
!
// can be contact or not!
monster.physicsBody.collisionBitMask = 0
Two category ids
static const uint32_t projectileCategory = 0x1 << 0;!
static const uint32_t monsterCategory = 0x1 << 1;
addMonster
- (void)addMonster { !
! // ignore …!
// physic!
monster.physicsBody = [SKPhysicsBody
bodyWithRectangleOfSize:monster.size]; // 1!
monster.physicsBody.dynamic = YES; // 2!
monster.physicsBody.categoryBitMask = monsterCategory; // 3!
monster.physicsBody.contactTestBitMask = projectileCategory; // 4!
monster.physicsBody.collisionBitMask = 0; // 5!
}
touchesBegan:withEvent:
projectile.physicsBody = [SKPhysicsBody
bodyWithCircleOfRadius:projectile.size.width/2];!
projectile.physicsBody.dynamic = YES;!
projectile.physicsBody.categoryBitMask = projectileCategory;!
projectile.physicsBody.contactTestBitMask = monsterCategory;!
projectile.physicsBody.collisionBitMask = 0;
SKPhysicsContactDelegate - impl
- (void)didBeginContact:(SKPhysicsContact *)contact!
{!
SKPhysicsBody *firstBody, *secondBody;!
!
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)!
{!
firstBody = contact.bodyA;!
secondBody = contact.bodyB;!
}!
else!
{!
firstBody = contact.bodyB;!
secondBody = contact.bodyA;!
}!
}
SKPhysicsContactDelegate - impl(2)
- (void)didBeginContact:(SKPhysicsContact *)contact!
{!
if ((firstBody.categoryBitMask & projectileCategory) != 0 &&!
(secondBody.categoryBitMask & monsterCategory) != 0){!
!
[self projectile:(SKSpriteNode *) firstBody.node
didCollideWithMonster:(SKSpriteNode *) secondBody.node];!
}!
}
Dismiss collided objects
- (void)projectile:(SKSpriteNode *)projectile
didCollideWithMonster:(SKSpriteNode *)monster {!
NSLog(@"Hit");!
[projectile removeFromParent];!
[monster removeFromParent];!
}
Run
About Music
Background Music - ViewController.m
#import <AVFoundation/AVFoundation.h>!
!
@interface ViewController ()!
@property (nonatomic) AVAudioPlayer * backgroundMusicPlayer;!
@end!
!
@implementation ViewController!
-(void) viewDidAppear:(BOOL)animated{!
! NSError *error;!
! NSURL * backgroundMusicURL = [[NSBundle mainBundle] URLForResource:@"background-
music-aac" withExtension:@"caf"];!
! self.backgroundMusicPlayer = [[AVAudioPlayer alloc]
initWithContentsOfURL:backgroundMusicURL error:&error];!
! self.backgroundMusicPlayer.numberOfLoops = -1;!
! [self.backgroundMusicPlayer prepareToPlay];!
! [self.backgroundMusicPlayer play];!
}!
@end
sound effect - touchesBegan:withEvent:
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{!
! [self runAction:[SKAction playSoundFileNamed:@"pew-pew-lei.caf"
waitForCompletion:NO]];!
!
}
Run
Change Scene
Create a new Scene
GameOverScene.h
#import <SpriteKit/SpriteKit.h>!
!
@interface GameOverScene : SKScene!
-(id)initWithSize:(CGSize)size won:(BOOL)won;!
@end
GameOverScene.m
#import "GameOverScene.h"!
#import "MyScene.h"!
@implementation GameOverScene!
!
-(id)initWithSize:(CGSize)size won:(BOOL)won {!
if (self = [super initWithSize:size]) {!
!
// 1!
self.backgroundColor = [SKColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];!
!
// 2!
NSString * message;!
if (won) {!
message = @"You Won!";!
} else {!
message = @"You Lose :[";!
}!
! ! // ignore … !
! }!
! return self;!
}!
@end
GameOverScene.m - Label
-(id)initWithSize:(CGSize)size won:(BOOL)won {!
if (self = [super initWithSize:size]) {!
! ! // ignored!
! ! SKLabelNode *label = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];!
label.text = message;!
label.fontSize = 40;!
label.fontColor = [SKColor blackColor];!
label.position = CGPointMake(self.size.width/2, self.size.height/2);!
[self addChild:label];!
! ! // ignored!
! }!
! return self;!
}
GameOverScene.m - Another Scene
-(id)initWithSize:(CGSize)size won:(BOOL)won {!
if (self = [super initWithSize:size]) {!
! ! // ignored!
! ! [self runAction:!
[SKAction sequence:@[!
[SKAction waitForDuration:3.0],!
[SKAction runBlock:^{!
// 5!
SKTransition *reveal = [SKTransition flipHorizontalWithDuration:0.5];!
SKScene * myScene = [[MyScene alloc] initWithSize:self.size];!
[self.view presentScene:myScene transition: reveal];!
}]!
]]!
];!
!
! }!
! return self;!
}
Show GameOverScene - MyScene.m
#import "GameOverScene.h"!
!
- (void)addMonster {!
! SKAction * loseAction = [SKAction runBlock:^{!
! ! SKTransition *reveal = [SKTransition flipHorizontalWithDuration:
0.5];!
! ! SKScene * gameOverScene = [[GameOverScene alloc]
initWithSize:self.size won:NO];!
! ! [self.view presentScene:gameOverScene transition: reveal];!
! }];!
! [monster runAction:[SKAction sequence:@[actionMove, loseAction,
actionMoveDone]]];!
}
Show Win
@interface MyScene ()<SKPhysicsContactDelegate>!
@property (nonatomic) int monstersDestroyed;!
@end
- (void)projectile:(SKSpriteNode *)projectile didCollideWithMonster:
(SKSpriteNode *)monster {!
self.monstersDestroyed++;!
if (self.monstersDestroyed > 5) {!
SKTransition *reveal = [SKTransition flipHorizontalWithDuration:0.5];!
SKScene * gameOverScene = [[GameOverScene alloc]
initWithSize:self.size won:YES];!
[self.view presentScene:gameOverScene transition: reveal];!
}!
}
Question ?

More Related Content

What's hot

Implement angular calendar component how to drag &amp; create events
Implement angular calendar component how to drag &amp; create eventsImplement angular calendar component how to drag &amp; create events
Implement angular calendar component how to drag &amp; create eventsKaty Slemon
 
Макс Грибов — Использование SpriteKit в неигровых приложениях
Макс Грибов — Использование SpriteKit в неигровых приложенияхМакс Грибов — Использование SpriteKit в неигровых приложениях
Макс Грибов — Использование SpriteKit в неигровых приложенияхCocoaHeads
 
Using Android Things to Detect & Exterminate Reptilians
Using Android Things to Detect & Exterminate ReptiliansUsing Android Things to Detect & Exterminate Reptilians
Using Android Things to Detect & Exterminate ReptiliansNilhcem
 
Project presentation(View calender)
Project presentation(View calender)Project presentation(View calender)
Project presentation(View calender)Ikhtiar Khan Sohan
 
The Ring programming language version 1.3 book - Part 49 of 88
The Ring programming language version 1.3 book - Part 49 of 88The Ring programming language version 1.3 book - Part 49 of 88
The Ring programming language version 1.3 book - Part 49 of 88Mahmoud Samir Fayed
 
Introduction to Immersive Web
Introduction to Immersive WebIntroduction to Immersive Web
Introduction to Immersive WebHirokazu Egashira
 
The 2016 Android Developer Toolbox [NANTES]
The 2016 Android Developer Toolbox [NANTES]The 2016 Android Developer Toolbox [NANTES]
The 2016 Android Developer Toolbox [NANTES]Nilhcem
 
How to Make Your Users Sick in 60 Seconds – About UX Design, WebVR and React VR
How to Make Your Users Sick in 60 Seconds – About UX Design, WebVR and React VRHow to Make Your Users Sick in 60 Seconds – About UX Design, WebVR and React VR
How to Make Your Users Sick in 60 Seconds – About UX Design, WebVR and React VRGeilDanke
 
HoloLens Programming Tutorial: AirTap & Spatial Mapping
HoloLens Programming Tutorial: AirTap & Spatial MappingHoloLens Programming Tutorial: AirTap & Spatial Mapping
HoloLens Programming Tutorial: AirTap & Spatial MappingTakashi Yoshinaga
 
Implementing a Simple Game using libGDX
Implementing a Simple Game using libGDXImplementing a Simple Game using libGDX
Implementing a Simple Game using libGDXJussi Pohjolainen
 
The Ring programming language version 1.5.1 book - Part 64 of 180
The Ring programming language version 1.5.1 book - Part 64 of 180The Ring programming language version 1.5.1 book - Part 64 of 180
The Ring programming language version 1.5.1 book - Part 64 of 180Mahmoud Samir Fayed
 
Standford 2015 week3: Objective-C Compatibility, Property List, Views
Standford 2015 week3: Objective-C Compatibility, Property List, ViewsStandford 2015 week3: Objective-C Compatibility, Property List, Views
Standford 2015 week3: Objective-C Compatibility, Property List, Views彼得潘 Pan
 
The Ring programming language version 1.5.2 book - Part 52 of 181
The Ring programming language version 1.5.2 book - Part 52 of 181The Ring programming language version 1.5.2 book - Part 52 of 181
The Ring programming language version 1.5.2 book - Part 52 of 181Mahmoud Samir Fayed
 
Augmented Reality in JavaScript
Augmented Reality in JavaScriptAugmented Reality in JavaScript
Augmented Reality in JavaScriptZeno Rocha
 
Home Automation with Android Things and the Google Assistant
Home Automation with Android Things and the Google AssistantHome Automation with Android Things and the Google Assistant
Home Automation with Android Things and the Google AssistantNilhcem
 
Android Wear Essentials
Android Wear EssentialsAndroid Wear Essentials
Android Wear EssentialsNilhcem
 

What's hot (20)

Implement angular calendar component how to drag &amp; create events
Implement angular calendar component how to drag &amp; create eventsImplement angular calendar component how to drag &amp; create events
Implement angular calendar component how to drag &amp; create events
 
Box2D and libGDX
Box2D and libGDXBox2D and libGDX
Box2D and libGDX
 
Макс Грибов — Использование SpriteKit в неигровых приложениях
Макс Грибов — Использование SpriteKit в неигровых приложенияхМакс Грибов — Использование SpriteKit в неигровых приложениях
Макс Грибов — Использование SpriteKit в неигровых приложениях
 
libGDX: Tiled Maps
libGDX: Tiled MapslibGDX: Tiled Maps
libGDX: Tiled Maps
 
Using Android Things to Detect & Exterminate Reptilians
Using Android Things to Detect & Exterminate ReptiliansUsing Android Things to Detect & Exterminate Reptilians
Using Android Things to Detect & Exterminate Reptilians
 
Project presentation(View calender)
Project presentation(View calender)Project presentation(View calender)
Project presentation(View calender)
 
WebXR if X = how?
WebXR if X = how?WebXR if X = how?
WebXR if X = how?
 
The Ring programming language version 1.3 book - Part 49 of 88
The Ring programming language version 1.3 book - Part 49 of 88The Ring programming language version 1.3 book - Part 49 of 88
The Ring programming language version 1.3 book - Part 49 of 88
 
Introduction to Immersive Web
Introduction to Immersive WebIntroduction to Immersive Web
Introduction to Immersive Web
 
The 2016 Android Developer Toolbox [NANTES]
The 2016 Android Developer Toolbox [NANTES]The 2016 Android Developer Toolbox [NANTES]
The 2016 Android Developer Toolbox [NANTES]
 
How to Make Your Users Sick in 60 Seconds – About UX Design, WebVR and React VR
How to Make Your Users Sick in 60 Seconds – About UX Design, WebVR and React VRHow to Make Your Users Sick in 60 Seconds – About UX Design, WebVR and React VR
How to Make Your Users Sick in 60 Seconds – About UX Design, WebVR and React VR
 
iOS Training Session-3
iOS Training Session-3iOS Training Session-3
iOS Training Session-3
 
HoloLens Programming Tutorial: AirTap & Spatial Mapping
HoloLens Programming Tutorial: AirTap & Spatial MappingHoloLens Programming Tutorial: AirTap & Spatial Mapping
HoloLens Programming Tutorial: AirTap & Spatial Mapping
 
Implementing a Simple Game using libGDX
Implementing a Simple Game using libGDXImplementing a Simple Game using libGDX
Implementing a Simple Game using libGDX
 
The Ring programming language version 1.5.1 book - Part 64 of 180
The Ring programming language version 1.5.1 book - Part 64 of 180The Ring programming language version 1.5.1 book - Part 64 of 180
The Ring programming language version 1.5.1 book - Part 64 of 180
 
Standford 2015 week3: Objective-C Compatibility, Property List, Views
Standford 2015 week3: Objective-C Compatibility, Property List, ViewsStandford 2015 week3: Objective-C Compatibility, Property List, Views
Standford 2015 week3: Objective-C Compatibility, Property List, Views
 
The Ring programming language version 1.5.2 book - Part 52 of 181
The Ring programming language version 1.5.2 book - Part 52 of 181The Ring programming language version 1.5.2 book - Part 52 of 181
The Ring programming language version 1.5.2 book - Part 52 of 181
 
Augmented Reality in JavaScript
Augmented Reality in JavaScriptAugmented Reality in JavaScript
Augmented Reality in JavaScript
 
Home Automation with Android Things and the Google Assistant
Home Automation with Android Things and the Google AssistantHome Automation with Android Things and the Google Assistant
Home Automation with Android Things and the Google Assistant
 
Android Wear Essentials
Android Wear EssentialsAndroid Wear Essentials
Android Wear Essentials
 

Similar to Shootting Game

Intro to Game Programming
Intro to Game ProgrammingIntro to Game Programming
Intro to Game ProgrammingRichard Jones
 
Useful Tools for Making Video Games - XNA (2008)
Useful Tools for Making Video Games - XNA (2008)Useful Tools for Making Video Games - XNA (2008)
Useful Tools for Making Video Games - XNA (2008)Korhan Bircan
 
Leaving Flatland: getting started with WebGL
Leaving Flatland: getting started with WebGLLeaving Flatland: getting started with WebGL
Leaving Flatland: getting started with WebGLgerbille
 
Useful Tools for Making Video Games - Irrlicht (2008)
Useful Tools for Making Video Games - Irrlicht (2008)Useful Tools for Making Video Games - Irrlicht (2008)
Useful Tools for Making Video Games - Irrlicht (2008)Korhan Bircan
 
Game development with Cocos2d
Game development with Cocos2dGame development with Cocos2d
Game development with Cocos2dVinsol
 
Making Games in JavaScript
Making Games in JavaScriptMaking Games in JavaScript
Making Games in JavaScriptSam Cartwright
 
HTML5: where flash isn't needed anymore
HTML5: where flash isn't needed anymoreHTML5: where flash isn't needed anymore
HTML5: where flash isn't needed anymoreRemy Sharp
 
cocos2d for i Phoneの紹介
cocos2d for i Phoneの紹介cocos2d for i Phoneの紹介
cocos2d for i Phoneの紹介Jun-ichi Shinde
 
Synchronizing without internet - Multipeer Connectivity (iOS)
Synchronizing without internet - Multipeer Connectivity (iOS)Synchronizing without internet - Multipeer Connectivity (iOS)
Synchronizing without internet - Multipeer Connectivity (iOS)Jorge Maroto
 
Browsers with Wings
Browsers with WingsBrowsers with Wings
Browsers with WingsRemy Sharp
 
I wanted to change the cloudsrectangles into an actuall image it do.pdf
I wanted to change the cloudsrectangles into an actuall image it do.pdfI wanted to change the cloudsrectangles into an actuall image it do.pdf
I wanted to change the cloudsrectangles into an actuall image it do.pdffeelinggifts
 
WebVR - MobileTechCon Berlin 2016
WebVR - MobileTechCon Berlin 2016WebVR - MobileTechCon Berlin 2016
WebVR - MobileTechCon Berlin 2016Carsten Sandtner
 
303 TANSTAAFL: Using Open Source iPhone UI Code
303 TANSTAAFL: Using Open Source iPhone UI Code303 TANSTAAFL: Using Open Source iPhone UI Code
303 TANSTAAFL: Using Open Source iPhone UI Codejonmarimba
 
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...DroidConTLV
 
Oxygine 2 d objects,events,debug and resources
Oxygine 2 d objects,events,debug and resourcesOxygine 2 d objects,events,debug and resources
Oxygine 2 d objects,events,debug and resourcescorehard_by
 
JavaScript Advanced - Useful methods to power up your code
JavaScript Advanced - Useful methods to power up your codeJavaScript Advanced - Useful methods to power up your code
JavaScript Advanced - Useful methods to power up your codeLaurence Svekis ✔
 
How to Clone Flappy Bird in Swift
How to Clone Flappy Bird in SwiftHow to Clone Flappy Bird in Swift
How to Clone Flappy Bird in SwiftGiordano Scalzo
 

Similar to Shootting Game (20)

Intro to Game Programming
Intro to Game ProgrammingIntro to Game Programming
Intro to Game Programming
 
Useful Tools for Making Video Games - XNA (2008)
Useful Tools for Making Video Games - XNA (2008)Useful Tools for Making Video Games - XNA (2008)
Useful Tools for Making Video Games - XNA (2008)
 
Leaving Flatland: getting started with WebGL
Leaving Flatland: getting started with WebGLLeaving Flatland: getting started with WebGL
Leaving Flatland: getting started with WebGL
 
Useful Tools for Making Video Games - Irrlicht (2008)
Useful Tools for Making Video Games - Irrlicht (2008)Useful Tools for Making Video Games - Irrlicht (2008)
Useful Tools for Making Video Games - Irrlicht (2008)
 
Game development with Cocos2d
Game development with Cocos2dGame development with Cocos2d
Game development with Cocos2d
 
Making Games in JavaScript
Making Games in JavaScriptMaking Games in JavaScript
Making Games in JavaScript
 
HTML5: where flash isn't needed anymore
HTML5: where flash isn't needed anymoreHTML5: where flash isn't needed anymore
HTML5: where flash isn't needed anymore
 
cocos2d for i Phoneの紹介
cocos2d for i Phoneの紹介cocos2d for i Phoneの紹介
cocos2d for i Phoneの紹介
 
Synchronizing without internet - Multipeer Connectivity (iOS)
Synchronizing without internet - Multipeer Connectivity (iOS)Synchronizing without internet - Multipeer Connectivity (iOS)
Synchronizing without internet - Multipeer Connectivity (iOS)
 
Intro to HTML5
Intro to HTML5Intro to HTML5
Intro to HTML5
 
Browsers with Wings
Browsers with WingsBrowsers with Wings
Browsers with Wings
 
I wanted to change the cloudsrectangles into an actuall image it do.pdf
I wanted to change the cloudsrectangles into an actuall image it do.pdfI wanted to change the cloudsrectangles into an actuall image it do.pdf
I wanted to change the cloudsrectangles into an actuall image it do.pdf
 
WebVR - MobileTechCon Berlin 2016
WebVR - MobileTechCon Berlin 2016WebVR - MobileTechCon Berlin 2016
WebVR - MobileTechCon Berlin 2016
 
Sbaw091117
Sbaw091117Sbaw091117
Sbaw091117
 
303 TANSTAAFL: Using Open Source iPhone UI Code
303 TANSTAAFL: Using Open Source iPhone UI Code303 TANSTAAFL: Using Open Source iPhone UI Code
303 TANSTAAFL: Using Open Source iPhone UI Code
 
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
 
14709302.ppt
14709302.ppt14709302.ppt
14709302.ppt
 
Oxygine 2 d objects,events,debug and resources
Oxygine 2 d objects,events,debug and resourcesOxygine 2 d objects,events,debug and resources
Oxygine 2 d objects,events,debug and resources
 
JavaScript Advanced - Useful methods to power up your code
JavaScript Advanced - Useful methods to power up your codeJavaScript Advanced - Useful methods to power up your code
JavaScript Advanced - Useful methods to power up your code
 
How to Clone Flappy Bird in Swift
How to Clone Flappy Bird in SwiftHow to Clone Flappy Bird in Swift
How to Clone Flappy Bird in Swift
 

More from Michael Pan

Introduction to Android Studio
Introduction to Android StudioIntroduction to Android Studio
Introduction to Android StudioMichael Pan
 
Eclipse and Genymotion
Eclipse and GenymotionEclipse and Genymotion
Eclipse and GenymotionMichael Pan
 
Strategy Pattern for Objective-C
Strategy Pattern for Objective-CStrategy Pattern for Objective-C
Strategy Pattern for Objective-CMichael Pan
 
Core data lightweight_migration
Core data lightweight_migrationCore data lightweight_migration
Core data lightweight_migrationMichael Pan
 
Google maps SDK for iOS 1.4
Google maps SDK for iOS 1.4Google maps SDK for iOS 1.4
Google maps SDK for iOS 1.4Michael Pan
 
Homework2 play cards
Homework2 play cardsHomework2 play cards
Homework2 play cardsMichael Pan
 
Autorelease pool
Autorelease poolAutorelease pool
Autorelease poolMichael Pan
 
Objc under the_hood_2013
Objc under the_hood_2013Objc under the_hood_2013
Objc under the_hood_2013Michael Pan
 
Prototype by Xcode
Prototype by XcodePrototype by Xcode
Prototype by XcodeMichael Pan
 
Superstar dj pdf
Superstar dj pdfSuperstar dj pdf
Superstar dj pdfMichael Pan
 
比價撿便宜 Steven
比價撿便宜 Steven比價撿便宜 Steven
比價撿便宜 StevenMichael Pan
 
Appsgaga - iOS Game Developer
Appsgaga - iOS Game DeveloperAppsgaga - iOS Game Developer
Appsgaga - iOS Game DeveloperMichael Pan
 
GZFox Inc. Jacky
GZFox Inc. JackyGZFox Inc. Jacky
GZFox Inc. JackyMichael Pan
 
創投公司 hoku_20121017
創投公司 hoku_20121017創投公司 hoku_20121017
創投公司 hoku_20121017Michael Pan
 
Opening iOS App 開發者交流會
Opening iOS App 開發者交流會Opening iOS App 開發者交流會
Opening iOS App 開發者交流會Michael Pan
 

More from Michael Pan (20)

Activity
ActivityActivity
Activity
 
Introduction to Android Studio
Introduction to Android StudioIntroduction to Android Studio
Introduction to Android Studio
 
Eclipse and Genymotion
Eclipse and GenymotionEclipse and Genymotion
Eclipse and Genymotion
 
Note something
Note somethingNote something
Note something
 
Strategy Pattern for Objective-C
Strategy Pattern for Objective-CStrategy Pattern for Objective-C
Strategy Pattern for Objective-C
 
Core data lightweight_migration
Core data lightweight_migrationCore data lightweight_migration
Core data lightweight_migration
 
Google maps SDK for iOS 1.4
Google maps SDK for iOS 1.4Google maps SDK for iOS 1.4
Google maps SDK for iOS 1.4
 
Homework2 play cards
Homework2 play cardsHomework2 play cards
Homework2 play cards
 
Autorelease pool
Autorelease poolAutorelease pool
Autorelease pool
 
Objc under the_hood_2013
Objc under the_hood_2013Objc under the_hood_2013
Objc under the_hood_2013
 
Prototype by Xcode
Prototype by XcodePrototype by Xcode
Prototype by Xcode
 
Dropbox sync
Dropbox syncDropbox sync
Dropbox sync
 
Nimbus
NimbusNimbus
Nimbus
 
Superstar dj pdf
Superstar dj pdfSuperstar dj pdf
Superstar dj pdf
 
ADB - Arthur
ADB - ArthurADB - Arthur
ADB - Arthur
 
比價撿便宜 Steven
比價撿便宜 Steven比價撿便宜 Steven
比價撿便宜 Steven
 
Appsgaga - iOS Game Developer
Appsgaga - iOS Game DeveloperAppsgaga - iOS Game Developer
Appsgaga - iOS Game Developer
 
GZFox Inc. Jacky
GZFox Inc. JackyGZFox Inc. Jacky
GZFox Inc. Jacky
 
創投公司 hoku_20121017
創投公司 hoku_20121017創投公司 hoku_20121017
創投公司 hoku_20121017
 
Opening iOS App 開發者交流會
Opening iOS App 開發者交流會Opening iOS App 開發者交流會
Opening iOS App 開發者交流會
 

Recently uploaded

LE IMPOSSIBRU QUIZ (Based on Splapp-me-do)
LE IMPOSSIBRU QUIZ (Based on Splapp-me-do)LE IMPOSSIBRU QUIZ (Based on Splapp-me-do)
LE IMPOSSIBRU QUIZ (Based on Splapp-me-do)bertfelixtorre
 
Call Girl Contact Number Andheri WhatsApp:+91-9833363713
Call Girl Contact Number Andheri WhatsApp:+91-9833363713Call Girl Contact Number Andheri WhatsApp:+91-9833363713
Call Girl Contact Number Andheri WhatsApp:+91-9833363713Sonam Pathan
 
5* Hotel Call Girls In Goa 7028418221 Call Girls In Calangute Beach Escort Se...
5* Hotel Call Girls In Goa 7028418221 Call Girls In Calangute Beach Escort Se...5* Hotel Call Girls In Goa 7028418221 Call Girls In Calangute Beach Escort Se...
5* Hotel Call Girls In Goa 7028418221 Call Girls In Calangute Beach Escort Se...Apsara Of India
 
8377087607 Full Enjoy @24/7 Call Girls in Patel Nagar Delhi NCR
8377087607 Full Enjoy @24/7 Call Girls in Patel Nagar Delhi NCR8377087607 Full Enjoy @24/7 Call Girls in Patel Nagar Delhi NCR
8377087607 Full Enjoy @24/7 Call Girls in Patel Nagar Delhi NCRdollysharma2066
 
The Fine Line Between Honest and Evil Comics by Salty Vixen
The Fine Line Between Honest and Evil Comics by Salty VixenThe Fine Line Between Honest and Evil Comics by Salty Vixen
The Fine Line Between Honest and Evil Comics by Salty VixenSalty Vixen Stories & More
 
Gripping Adult Web Series You Can't Afford to Miss
Gripping Adult Web Series You Can't Afford to MissGripping Adult Web Series You Can't Afford to Miss
Gripping Adult Web Series You Can't Afford to Missget joys
 
Udaipur Call Girls 9602870969 Call Girl in Udaipur Rajasthan
Udaipur Call Girls 9602870969 Call Girl in Udaipur RajasthanUdaipur Call Girls 9602870969 Call Girl in Udaipur Rajasthan
Udaipur Call Girls 9602870969 Call Girl in Udaipur RajasthanApsara Of India
 
VIP Call Girls In Goa 7028418221 Call Girls In Baga Beach Escorts Service
VIP Call Girls In Goa 7028418221 Call Girls In Baga Beach Escorts ServiceVIP Call Girls In Goa 7028418221 Call Girls In Baga Beach Escorts Service
VIP Call Girls In Goa 7028418221 Call Girls In Baga Beach Escorts ServiceApsara Of India
 
Call Girls Near Delhi Pride Hotel New Delhi 9873777170
Call Girls Near Delhi Pride Hotel New Delhi 9873777170Call Girls Near Delhi Pride Hotel New Delhi 9873777170
Call Girls Near Delhi Pride Hotel New Delhi 9873777170Sonam Pathan
 
Call Girls Near Taurus Sarovar Portico Hotel New Delhi 9873777170
Call Girls Near Taurus Sarovar Portico Hotel New Delhi 9873777170Call Girls Near Taurus Sarovar Portico Hotel New Delhi 9873777170
Call Girls Near Taurus Sarovar Portico Hotel New Delhi 9873777170Sonam Pathan
 
Authentic No 1 Amil Baba In Pakistan Authentic No 1 Amil Baba In Karachi No 1...
Authentic No 1 Amil Baba In Pakistan Authentic No 1 Amil Baba In Karachi No 1...Authentic No 1 Amil Baba In Pakistan Authentic No 1 Amil Baba In Karachi No 1...
Authentic No 1 Amil Baba In Pakistan Authentic No 1 Amil Baba In Karachi No 1...First NO1 World Amil baba in Faisalabad
 
Kolkata Call Girl Howrah 👉 8250192130 ❣️💯 Available With Room 24×7
Kolkata Call Girl Howrah 👉 8250192130 ❣️💯 Available With Room 24×7Kolkata Call Girl Howrah 👉 8250192130 ❣️💯 Available With Room 24×7
Kolkata Call Girl Howrah 👉 8250192130 ❣️💯 Available With Room 24×7Riya Pathan
 
Hifi Laxmi Nagar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ D...
Hifi Laxmi Nagar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ D...Hifi Laxmi Nagar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ D...
Hifi Laxmi Nagar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ D...srsj9000
 
High Profile Call Girls Sodepur - 8250192130 Escorts Service with Real Photos...
High Profile Call Girls Sodepur - 8250192130 Escorts Service with Real Photos...High Profile Call Girls Sodepur - 8250192130 Escorts Service with Real Photos...
High Profile Call Girls Sodepur - 8250192130 Escorts Service with Real Photos...Riya Pathan
 
Cash Payment Contact:- 7028418221 Goa Call Girls Service North Goa Escorts
Cash Payment Contact:- 7028418221 Goa Call Girls Service North Goa EscortsCash Payment Contact:- 7028418221 Goa Call Girls Service North Goa Escorts
Cash Payment Contact:- 7028418221 Goa Call Girls Service North Goa EscortsApsara Of India
 
Fun Call Girls In Goa 7028418221 Escort Service In Morjim Beach Call Girl
Fun Call Girls In Goa 7028418221 Escort Service In Morjim Beach Call GirlFun Call Girls In Goa 7028418221 Escort Service In Morjim Beach Call Girl
Fun Call Girls In Goa 7028418221 Escort Service In Morjim Beach Call GirlApsara Of India
 
Call Girls In Karnal O8860008073 Sector 6 7 8 9 Karnal Escorts
Call Girls In Karnal O8860008073 Sector 6 7 8 9 Karnal EscortsCall Girls In Karnal O8860008073 Sector 6 7 8 9 Karnal Escorts
Call Girls In Karnal O8860008073 Sector 6 7 8 9 Karnal EscortsApsara Of India
 
Call US '' 8377087607'' !! Call Girls In Model Town Metro (Delhi NCR)
Call US '' 8377087607'' !! Call Girls In Model Town Metro (Delhi NCR)Call US '' 8377087607'' !! Call Girls In Model Town Metro (Delhi NCR)
Call US '' 8377087607'' !! Call Girls In Model Town Metro (Delhi NCR)dollysharma2066
 
Call Girls Ellis Bridge 7397865700 Independent Call Girls
Call Girls Ellis Bridge 7397865700 Independent Call GirlsCall Girls Ellis Bridge 7397865700 Independent Call Girls
Call Girls Ellis Bridge 7397865700 Independent Call Girlsssuser7cb4ff
 
Air-Hostess Call Girls Shobhabazar | 8250192130 At Low Cost Cash Payment Booking
Air-Hostess Call Girls Shobhabazar | 8250192130 At Low Cost Cash Payment BookingAir-Hostess Call Girls Shobhabazar | 8250192130 At Low Cost Cash Payment Booking
Air-Hostess Call Girls Shobhabazar | 8250192130 At Low Cost Cash Payment BookingRiya Pathan
 

Recently uploaded (20)

LE IMPOSSIBRU QUIZ (Based on Splapp-me-do)
LE IMPOSSIBRU QUIZ (Based on Splapp-me-do)LE IMPOSSIBRU QUIZ (Based on Splapp-me-do)
LE IMPOSSIBRU QUIZ (Based on Splapp-me-do)
 
Call Girl Contact Number Andheri WhatsApp:+91-9833363713
Call Girl Contact Number Andheri WhatsApp:+91-9833363713Call Girl Contact Number Andheri WhatsApp:+91-9833363713
Call Girl Contact Number Andheri WhatsApp:+91-9833363713
 
5* Hotel Call Girls In Goa 7028418221 Call Girls In Calangute Beach Escort Se...
5* Hotel Call Girls In Goa 7028418221 Call Girls In Calangute Beach Escort Se...5* Hotel Call Girls In Goa 7028418221 Call Girls In Calangute Beach Escort Se...
5* Hotel Call Girls In Goa 7028418221 Call Girls In Calangute Beach Escort Se...
 
8377087607 Full Enjoy @24/7 Call Girls in Patel Nagar Delhi NCR
8377087607 Full Enjoy @24/7 Call Girls in Patel Nagar Delhi NCR8377087607 Full Enjoy @24/7 Call Girls in Patel Nagar Delhi NCR
8377087607 Full Enjoy @24/7 Call Girls in Patel Nagar Delhi NCR
 
The Fine Line Between Honest and Evil Comics by Salty Vixen
The Fine Line Between Honest and Evil Comics by Salty VixenThe Fine Line Between Honest and Evil Comics by Salty Vixen
The Fine Line Between Honest and Evil Comics by Salty Vixen
 
Gripping Adult Web Series You Can't Afford to Miss
Gripping Adult Web Series You Can't Afford to MissGripping Adult Web Series You Can't Afford to Miss
Gripping Adult Web Series You Can't Afford to Miss
 
Udaipur Call Girls 9602870969 Call Girl in Udaipur Rajasthan
Udaipur Call Girls 9602870969 Call Girl in Udaipur RajasthanUdaipur Call Girls 9602870969 Call Girl in Udaipur Rajasthan
Udaipur Call Girls 9602870969 Call Girl in Udaipur Rajasthan
 
VIP Call Girls In Goa 7028418221 Call Girls In Baga Beach Escorts Service
VIP Call Girls In Goa 7028418221 Call Girls In Baga Beach Escorts ServiceVIP Call Girls In Goa 7028418221 Call Girls In Baga Beach Escorts Service
VIP Call Girls In Goa 7028418221 Call Girls In Baga Beach Escorts Service
 
Call Girls Near Delhi Pride Hotel New Delhi 9873777170
Call Girls Near Delhi Pride Hotel New Delhi 9873777170Call Girls Near Delhi Pride Hotel New Delhi 9873777170
Call Girls Near Delhi Pride Hotel New Delhi 9873777170
 
Call Girls Near Taurus Sarovar Portico Hotel New Delhi 9873777170
Call Girls Near Taurus Sarovar Portico Hotel New Delhi 9873777170Call Girls Near Taurus Sarovar Portico Hotel New Delhi 9873777170
Call Girls Near Taurus Sarovar Portico Hotel New Delhi 9873777170
 
Authentic No 1 Amil Baba In Pakistan Authentic No 1 Amil Baba In Karachi No 1...
Authentic No 1 Amil Baba In Pakistan Authentic No 1 Amil Baba In Karachi No 1...Authentic No 1 Amil Baba In Pakistan Authentic No 1 Amil Baba In Karachi No 1...
Authentic No 1 Amil Baba In Pakistan Authentic No 1 Amil Baba In Karachi No 1...
 
Kolkata Call Girl Howrah 👉 8250192130 ❣️💯 Available With Room 24×7
Kolkata Call Girl Howrah 👉 8250192130 ❣️💯 Available With Room 24×7Kolkata Call Girl Howrah 👉 8250192130 ❣️💯 Available With Room 24×7
Kolkata Call Girl Howrah 👉 8250192130 ❣️💯 Available With Room 24×7
 
Hifi Laxmi Nagar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ D...
Hifi Laxmi Nagar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ D...Hifi Laxmi Nagar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ D...
Hifi Laxmi Nagar Call Girls Service WhatsApp -> 9999965857 Available 24x7 ^ D...
 
High Profile Call Girls Sodepur - 8250192130 Escorts Service with Real Photos...
High Profile Call Girls Sodepur - 8250192130 Escorts Service with Real Photos...High Profile Call Girls Sodepur - 8250192130 Escorts Service with Real Photos...
High Profile Call Girls Sodepur - 8250192130 Escorts Service with Real Photos...
 
Cash Payment Contact:- 7028418221 Goa Call Girls Service North Goa Escorts
Cash Payment Contact:- 7028418221 Goa Call Girls Service North Goa EscortsCash Payment Contact:- 7028418221 Goa Call Girls Service North Goa Escorts
Cash Payment Contact:- 7028418221 Goa Call Girls Service North Goa Escorts
 
Fun Call Girls In Goa 7028418221 Escort Service In Morjim Beach Call Girl
Fun Call Girls In Goa 7028418221 Escort Service In Morjim Beach Call GirlFun Call Girls In Goa 7028418221 Escort Service In Morjim Beach Call Girl
Fun Call Girls In Goa 7028418221 Escort Service In Morjim Beach Call Girl
 
Call Girls In Karnal O8860008073 Sector 6 7 8 9 Karnal Escorts
Call Girls In Karnal O8860008073 Sector 6 7 8 9 Karnal EscortsCall Girls In Karnal O8860008073 Sector 6 7 8 9 Karnal Escorts
Call Girls In Karnal O8860008073 Sector 6 7 8 9 Karnal Escorts
 
Call US '' 8377087607'' !! Call Girls In Model Town Metro (Delhi NCR)
Call US '' 8377087607'' !! Call Girls In Model Town Metro (Delhi NCR)Call US '' 8377087607'' !! Call Girls In Model Town Metro (Delhi NCR)
Call US '' 8377087607'' !! Call Girls In Model Town Metro (Delhi NCR)
 
Call Girls Ellis Bridge 7397865700 Independent Call Girls
Call Girls Ellis Bridge 7397865700 Independent Call GirlsCall Girls Ellis Bridge 7397865700 Independent Call Girls
Call Girls Ellis Bridge 7397865700 Independent Call Girls
 
Air-Hostess Call Girls Shobhabazar | 8250192130 At Low Cost Cash Payment Booking
Air-Hostess Call Girls Shobhabazar | 8250192130 At Low Cost Cash Payment BookingAir-Hostess Call Girls Shobhabazar | 8250192130 At Low Cost Cash Payment Booking
Air-Hostess Call Girls Shobhabazar | 8250192130 At Low Cost Cash Payment Booking
 

Shootting Game

  • 1. Sprite Kit - Case Study Michael Pan
  • 4. About Game 2D - Corona! 3D - Unity
  • 5. What we will build http://www.raywenderlich.com/42699/spritekit-tutorial-for-beginners
  • 6. Create a Sprite Kit Project Shooter
  • 11. MyScene.m #import "MyScene.h"! ! @interface MyScene ()! @property (nonatomic) SKSpriteNode * player;! @end! ! @implementation MyScene! ! -(id)initWithSize:(CGSize)size { ! if (self = [super initWithSize:size]) {! ! NSLog(@"Size: %@", NSStringFromCGSize(size));! ! self.backgroundColor = [SKColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];! self.player = [SKSpriteNode spriteNodeWithImageNamed:@"player"];! self.player.position = CGPointMake(100, 100);! [self addChild:self.player];! }! return self;! }! @end
  • 12. Run
  • 15. Modify the ViewController.m - (void)viewDidLoad! {! [super viewDidLoad];! ! // Configure the view.! SKView * skView = (SKView *)self.view;! skView.showsFPS = YES;! skView.showsNodeCount = YES;! ! // Create and configure the scene.! SKScene * scene = [MyScene sceneWithSize:skView.bounds.size];! scene.scaleMode = SKSceneScaleModeAspectFill;! ! // Present the scene.! [skView presentScene:scene];! }
  • 16. viewDidAppear -(void) viewDidAppear:(BOOL)animated{! [super viewDidAppear:animated];! SKView * skView = (SKView *)self.view;! ! skView.showsFPS = YES;! skView.showsNodeCount = YES;! ! // Create and configure the scene.! SKScene * scene = [MyScene sceneWithSize:skView.bounds.size];! scene.scaleMode = SKSceneScaleModeAspectFill;! ! // Present the scene.! [skView presentScene:scene];! }
  • 18. What we learned SKScene SKSpriteNode self.player = [SKSpriteNode spriteNodeWithImageNamed:@"player"];! self.player.position = CGPointMake(100, 100);! [self addChild:self.player];
  • 21. Put SpriteNode on scene - right-down?? SKScene (0,0) (100,100)
  • 22. Put SpriteNode on scene - left-up ?? SKScene (0,0) (100,100)
  • 23. Put SpriteNode on scene - center ?? SKScene (0,0) (100,100)
  • 24. Anchor point (0,0) (1,0) (0,1) (1,1) (0.5,0.5) default
  • 25. Test - position (0,0) with default Anchor Point self.player = [SKSpriteNode spriteNodeWithImageNamed:@"player"];! self.player.position = CGPointMake(0, 0);! [self addChild:self.player];
  • 26. Test - position (0,0) with default Anchor Point(0,0) self.player = [SKSpriteNode spriteNodeWithImageNamed:@"player"];! self.player.position = CGPointMake(0, 0);! self.player.anchorPoint = CGPointMake(0, 0);! [self addChild:self.player];
  • 27. Add enemy in MyScene.m (1) - (void)addMonster {! // Create sprite! SKSpriteNode * monster = [SKSpriteNode spriteNodeWithImageNamed:@"monster"];!  ! // Determine where to spawn the monster along the Y axis! int minY = monster.size.height / 2;! int maxY = self.frame.size.height - monster.size.height / 2;! int rangeY = maxY - minY;! int actualY = (arc4random() % rangeY) + minY;! ! monster.position = CGPointMake(self.frame.size.width + monster.size.width/2, actualY);! [self addChild:monster];! }
  • 28. Add enemy in MyScene.m (2) - (void)addMonster {!  ! //…! // Determine speed of the monster! int minDuration = 2.0;! int maxDuration = 4.0;! int rangeDuration = maxDuration - minDuration;! int actualDuration = (arc4random() % rangeDuration) + minDuration;!  ! // Create the actions! SKAction * actionMove = [SKAction moveTo:CGPointMake(-monster.size.width/2, actualY) duration:actualDuration];! SKAction * actionMoveDone = [SKAction removeFromParent];! [monster runAction:[SKAction sequence:@[actionMove, actionMoveDone]]];!  ! }
  • 31. - (void)update:(NSTimeInterval)currentTime every 1/60 second will be called automatically
  • 32. Stabilise the time interval @interface MyScene ()! @property (nonatomic) SKSpriteNode * player;! @property (nonatomic) NSTimeInterval lastSpawnTimeInterval;! @property (nonatomic) NSTimeInterval lastUpdateTimeInterval;! @end
  • 33. Codes in update: - (void)update:(NSTimeInterval)currentTime {! CFTimeInterval timeSinceLast = currentTime - self.lastUpdateTimeInterval;! self.lastUpdateTimeInterval = currentTime;! if (timeSinceLast > 1) {! timeSinceLast = 1.0 / 60.0;! self.lastUpdateTimeInterval = currentTime;! }! [self updateWithTimeSinceLastUpdate:timeSinceLast];! ! }
  • 34. Every second add a enemy - (void)updateWithTimeSinceLastUpdate: (CFTimeInterval)timeSinceLast {!  ! self.lastSpawnTimeInterval += timeSinceLast;! if (self.lastSpawnTimeInterval > 1) {! self.lastSpawnTimeInterval = 0;! [self addMonster];! }! }!
  • 37. Throw projectile - vector (spriteX, spriteY) offsetX offsetY (touchX, touchY) offsetX = touchX - spriteX offsetY = touchY - spriteY
  • 38. Define helper function - offset CGPoint subPoint(CGPoint a, CGPoint b ){! CGPoint subPoint = CGPointMake(a.x - b.x, a.y - b.y);! return subPoint;! }
  • 39. Unit value of vector offsetX = touchX - spriteX offsetY = touchY - spriteY unitValue = sqrt(offsetX^2 + offsetY^2) Normalised vector = (offsetX / unitValue , offsetY / unitValue) offsetX offsetY unitValue
  • 40. Define helper function - normalised offset CGPoint normalisedPoint(CGPoint offset){! CGFloat nValue = sqrtf(offset.x*offset.x + offset.y*offset.y);! CGPoint nPoint = CGPointMake(offset.x/nValue, offset.y/nValue);! return nPoint;! }
  • 41. Get touch event - add projectile -(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{! ! UITouch * touch = [touches anyObject];! ! // get the location in the scene! CGPoint location = [touch locationInNode:self] ;! ! SKSpriteNode * projectile = [SKSpriteNode spriteNodeWithImageNamed:@"projectile"];! projectile.position = self.player.position;! ! CGPoint offset = subPoint(location, projectile.position);! ! if (offset.x <= 0) return;! ! [self addChild:projectile];! }
  • 42. Multiply vector - helper function CGPoint multiplyVector(CGPoint vector, CGFloat amount){! CGPoint newVec = CGPointMake(vector.x*amount, vector.y*amount);! return newVec;! }
  • 43. Calculate projectile destination (offsetX, offsetY) (offsetX/unitValue, offsetY/unitValue) newVec = multiplyVector(offset, 1000) (player.x+newVec.x, player.y+newVec.y)
  • 44. Add point with offset CGPoint addOffset(CGPoint a, CGPoint offset){! CGPoint newVec = CGPointMake(a.x+offset.x, a.y+offset.y);! return newVec;! }
  • 45. Get touch event - cal projectile destination -(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{! ! // ! ! CGPoint direction = normalisedPoint(offset);! ! ! ! CGPoint shootOffset = multiplyVector(direction, 1000);! ! ! CGPoint realDest = addOffset(projectile.position, shootOffset);! ! ! float velocity = 480.0/1.0;! ! float realMoveDuration = self.size.width / velocity;! ! SKAction * actionMove = [SKAction moveTo:realDest duration:realMoveDuration];! ! SKAction * actionMoveDone = [SKAction removeFromParent];! ! [projectile runAction:[SKAction sequence:@[actionMove, actionMoveDone]]];! }
  • 46. Run
  • 47. Rotate the projectile float velocity = 480.0/1.0;! float realMoveDuration = self.size.width / velocity;! SKAction * actionMove = [SKAction moveTo:realDest duration:realMoveDuration];! SKAction * actionMoveDone = [SKAction removeFromParent];! SKAction * sequence = [SKAction sequence:@[actionMove, actionMoveDone]];! ! SKAction * rotate = [SKAction rotateByAngle:4*M_PI duration:0.5];! SKAction * forever = [SKAction repeatActionForever:rotate];! SKAction * group = [SKAction group:@[forever,sequence]];! [projectile runAction:group];
  • 48. Run
  • 50. Use the power of Physic Engine Set gravity! ! Set contact delegate self.physicsWorld.gravity = CGVectorMake(0,0); self.physicsWorld.contactDelegate = self;
  • 51. @interface MyScene ()<SKPhysicsContactDelegate>! @property (nonatomic) SKSpriteNode * player;! @property (nonatomic) NSTimeInterval lastSpawnTimeInterval;! @property (nonatomic) NSTimeInterval lastUpdateTimeInterval;! @end SKPhysicsContactDelegate
  • 52. physicsWorld @interface SKScene : SKEffectNode! ! @property (SK_NONATOMIC_IOSONLY, readonly) SKPhysicsWorld *physicsWorld;! ! @end
  • 53. physicsBody monster body! ! projectile body monster.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:monster.size]; projectile.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:projectile.size.width/2];
  • 54. physics attributes // movable! monster.physicsBody.dynamic = YES;! ! // like ID! monster.physicsBody.categoryBitMask = monsterCategory;! ! // which ID will be contact! monster.physicsBody.contactTestBitMask = projectileCategory;! ! // can be contact or not! monster.physicsBody.collisionBitMask = 0
  • 55. Two category ids static const uint32_t projectileCategory = 0x1 << 0;! static const uint32_t monsterCategory = 0x1 << 1;
  • 56. addMonster - (void)addMonster { ! ! // ignore …! // physic! monster.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:monster.size]; // 1! monster.physicsBody.dynamic = YES; // 2! monster.physicsBody.categoryBitMask = monsterCategory; // 3! monster.physicsBody.contactTestBitMask = projectileCategory; // 4! monster.physicsBody.collisionBitMask = 0; // 5! }
  • 57. touchesBegan:withEvent: projectile.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:projectile.size.width/2];! projectile.physicsBody.dynamic = YES;! projectile.physicsBody.categoryBitMask = projectileCategory;! projectile.physicsBody.contactTestBitMask = monsterCategory;! projectile.physicsBody.collisionBitMask = 0;
  • 58. SKPhysicsContactDelegate - impl - (void)didBeginContact:(SKPhysicsContact *)contact! {! SKPhysicsBody *firstBody, *secondBody;! ! if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)! {! firstBody = contact.bodyA;! secondBody = contact.bodyB;! }! else! {! firstBody = contact.bodyB;! secondBody = contact.bodyA;! }! }
  • 59. SKPhysicsContactDelegate - impl(2) - (void)didBeginContact:(SKPhysicsContact *)contact! {! if ((firstBody.categoryBitMask & projectileCategory) != 0 &&! (secondBody.categoryBitMask & monsterCategory) != 0){! ! [self projectile:(SKSpriteNode *) firstBody.node didCollideWithMonster:(SKSpriteNode *) secondBody.node];! }! }
  • 60. Dismiss collided objects - (void)projectile:(SKSpriteNode *)projectile didCollideWithMonster:(SKSpriteNode *)monster {! NSLog(@"Hit");! [projectile removeFromParent];! [monster removeFromParent];! }
  • 61. Run
  • 63. Background Music - ViewController.m #import <AVFoundation/AVFoundation.h>! ! @interface ViewController ()! @property (nonatomic) AVAudioPlayer * backgroundMusicPlayer;! @end! ! @implementation ViewController! -(void) viewDidAppear:(BOOL)animated{! ! NSError *error;! ! NSURL * backgroundMusicURL = [[NSBundle mainBundle] URLForResource:@"background- music-aac" withExtension:@"caf"];! ! self.backgroundMusicPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:backgroundMusicURL error:&error];! ! self.backgroundMusicPlayer.numberOfLoops = -1;! ! [self.backgroundMusicPlayer prepareToPlay];! ! [self.backgroundMusicPlayer play];! }! @end
  • 64. sound effect - touchesBegan:withEvent: -(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{! ! [self runAction:[SKAction playSoundFileNamed:@"pew-pew-lei.caf" waitForCompletion:NO]];! ! }
  • 65. Run
  • 67. Create a new Scene
  • 68. GameOverScene.h #import <SpriteKit/SpriteKit.h>! ! @interface GameOverScene : SKScene! -(id)initWithSize:(CGSize)size won:(BOOL)won;! @end
  • 69. GameOverScene.m #import "GameOverScene.h"! #import "MyScene.h"! @implementation GameOverScene! ! -(id)initWithSize:(CGSize)size won:(BOOL)won {! if (self = [super initWithSize:size]) {! ! // 1! self.backgroundColor = [SKColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];! ! // 2! NSString * message;! if (won) {! message = @"You Won!";! } else {! message = @"You Lose :[";! }! ! ! // ignore … ! ! }! ! return self;! }! @end
  • 70. GameOverScene.m - Label -(id)initWithSize:(CGSize)size won:(BOOL)won {! if (self = [super initWithSize:size]) {! ! ! // ignored! ! ! SKLabelNode *label = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];! label.text = message;! label.fontSize = 40;! label.fontColor = [SKColor blackColor];! label.position = CGPointMake(self.size.width/2, self.size.height/2);! [self addChild:label];! ! ! // ignored! ! }! ! return self;! }
  • 71. GameOverScene.m - Another Scene -(id)initWithSize:(CGSize)size won:(BOOL)won {! if (self = [super initWithSize:size]) {! ! ! // ignored! ! ! [self runAction:! [SKAction sequence:@[! [SKAction waitForDuration:3.0],! [SKAction runBlock:^{! // 5! SKTransition *reveal = [SKTransition flipHorizontalWithDuration:0.5];! SKScene * myScene = [[MyScene alloc] initWithSize:self.size];! [self.view presentScene:myScene transition: reveal];! }]! ]]! ];! ! ! }! ! return self;! }
  • 72. Show GameOverScene - MyScene.m #import "GameOverScene.h"! ! - (void)addMonster {! ! SKAction * loseAction = [SKAction runBlock:^{! ! ! SKTransition *reveal = [SKTransition flipHorizontalWithDuration: 0.5];! ! ! SKScene * gameOverScene = [[GameOverScene alloc] initWithSize:self.size won:NO];! ! ! [self.view presentScene:gameOverScene transition: reveal];! ! }];! ! [monster runAction:[SKAction sequence:@[actionMove, loseAction, actionMoveDone]]];! }
  • 73. Show Win @interface MyScene ()<SKPhysicsContactDelegate>! @property (nonatomic) int monstersDestroyed;! @end - (void)projectile:(SKSpriteNode *)projectile didCollideWithMonster: (SKSpriteNode *)monster {! self.monstersDestroyed++;! if (self.monstersDestroyed > 5) {! SKTransition *reveal = [SKTransition flipHorizontalWithDuration:0.5];! SKScene * gameOverScene = [[GameOverScene alloc] initWithSize:self.size won:YES];! [self.view presentScene:gameOverScene transition: reveal];! }! }