Skip to content

Commit

Permalink
Start PingPong
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesdouble committed Mar 6, 2017
1 parent 81a0872 commit 88c34e7
Show file tree
Hide file tree
Showing 5 changed files with 317 additions and 101 deletions.
12 changes: 12 additions & 0 deletions JDGamesLoading.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
4F5C270C1E520BC400618FA7 /* JDGamesLoadingUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F5C270B1E520BC400618FA7 /* JDGamesLoadingUITests.swift */; };
4F5C271D1E520C9B00618FA7 /* JDBreaksScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F5C271B1E520C9B00618FA7 /* JDBreaksScene.swift */; };
4F5C27201E520D8600618FA7 /* JDGamesLoading.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F5C271F1E520D8600618FA7 /* JDGamesLoading.swift */; };
4FCDAE9E1E6D4E7900B83D2C /* JDPingPongScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FCDAE9D1E6D4E7800B83D2C /* JDPingPongScene.swift */; };
4FF1D95A1E52AE6E00EBA98E /* JDSnackScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FF1D9591E52AE6E00EBA98E /* JDSnackScene.swift */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -52,6 +53,7 @@
4F5C270D1E520BC400618FA7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
4F5C271B1E520C9B00618FA7 /* JDBreaksScene.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JDBreaksScene.swift; sourceTree = "<group>"; };
4F5C271F1E520D8600618FA7 /* JDGamesLoading.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JDGamesLoading.swift; sourceTree = "<group>"; };
4FCDAE9D1E6D4E7800B83D2C /* JDPingPongScene.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JDPingPongScene.swift; sourceTree = "<group>"; };
4FF1D9591E52AE6E00EBA98E /* JDSnackScene.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JDSnackScene.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -135,6 +137,7 @@
4F5C27191E520C8300618FA7 /* JDGamesLoading */ = {
isa = PBXGroup;
children = (
4FCDAE9C1E6D4E4200B83D2C /* PingPongGame */,
4FF1D9581E52ADBB00EBA98E /* SnackGame */,
4F5C271A1E520C8F00618FA7 /* BreaksGame */,
4F5C271F1E520D8600618FA7 /* JDGamesLoading.swift */,
Expand All @@ -150,6 +153,14 @@
name = BreaksGame;
sourceTree = "<group>";
};
4FCDAE9C1E6D4E4200B83D2C /* PingPongGame */ = {
isa = PBXGroup;
children = (
4FCDAE9D1E6D4E7800B83D2C /* JDPingPongScene.swift */,
);
name = PingPongGame;
sourceTree = "<group>";
};
4FF1D9581E52ADBB00EBA98E /* SnackGame */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -292,6 +303,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4FCDAE9E1E6D4E7900B83D2C /* JDPingPongScene.swift in Sources */,
4F5C26EE1E520BC400618FA7 /* ViewController.swift in Sources */,
4F5C27201E520D8600618FA7 /* JDGamesLoading.swift in Sources */,
4FF1D95A1E52AE6E00EBA98E /* JDSnackScene.swift in Sources */,
Expand Down
215 changes: 127 additions & 88 deletions JDGamesLoading/JDBreaksScene.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,112 @@ struct JDBreaksGameConfiguration {
var paddle_color:UIColor = UIColor.white
var ball_color:UIColor = UIColor.white
var block_color:UIColor = UIColor.white
var blocks_count:Int = 3
var RowCount:Int = 1
var ColumnCount:Int = 3
}

struct BreaksBasicSetting {
static let BallCategoryName = "ball"
static let PaddleCategoryName = "paddle"
static let BlockCategoryName = "block"
static let GameMessageName = "gameMessage"

static let BallCategory : UInt32 = 0x1 << 0
static let BlockCategory : UInt32 = 0x1 << 1
static let PaddleCategory : UInt32 = 0x1 << 2
static let BorderCategory : UInt32 = 0x1 << 3
}

class JDBreaksBrick:SKShapeNode
{
init(size:CGSize,color:UIColor) {
super.init()
let rect = CGRect(origin: CGPoint.zero, size: size)
self.path = CGPath(rect: rect, transform: nil)

self.strokeColor = UIColor.black
self.fillColor = color
self.physicsBody = SKPhysicsBody(rectangleOf: self.frame.size)
self.physicsBody!.allowsRotation = false
self.physicsBody!.friction = 0.0
self.physicsBody!.affectedByGravity = false
self.physicsBody!.isDynamic = false
self.name = BreaksBasicSetting.BlockCategoryName
self.physicsBody!.categoryBitMask = BreaksBasicSetting.BlockCategory
self.zPosition = 2
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

class JDBallNode:SKShapeNode
{
init(size:CGSize,color:UIColor) {
super.init()
let rect = CGRect(origin: CGPoint.zero, size: size)
self.path = CGPath(roundedRect: rect, cornerWidth: size.width * 0.5, cornerHeight: size.width * 0.5, transform: nil)
//
self.fillColor = color
self.position = CGPoint(x: self.frame.width * 0.5, y: self.frame.width * 0.5)
self.name = BreaksBasicSetting.BallCategoryName
self.physicsBody = SKPhysicsBody(circleOfRadius: self.frame.width * 0.5)
self.physicsBody!.categoryBitMask = BreaksBasicSetting.BallCategory
self.physicsBody!.isDynamic = true
self.physicsBody!.friction = 0.0
self.physicsBody!.restitution = 1.0
self.physicsBody!.linearDamping = 0.0
self.physicsBody!.angularDamping = 0.0
self.physicsBody!.allowsRotation = false
self.physicsBody!.contactTestBitMask = BreaksBasicSetting.BlockCategory
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

class JDBreakPaddle:SKShapeNode
{
init(size:CGSize,color:UIColor,radius:CGFloat) {
super.init()
let rect = CGRect(origin: CGPoint.zero, size: size)
self.path = CGPath(roundedRect: rect, cornerWidth: radius, cornerHeight: radius, transform: nil)
//
self.fillColor = color
self.name = BreaksBasicSetting.PaddleCategoryName
self.physicsBody = SKPhysicsBody(rectangleOf: self.frame.size)
self.physicsBody!.categoryBitMask = BreaksBasicSetting.PaddleCategory
self.physicsBody!.isDynamic = false
self.physicsBody!.allowsRotation = true
self.physicsBody!.angularDamping = 0.1
self.physicsBody!.linearDamping = 0.1

}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}


class JDBreaksScene: SKScene
{

let BallCategoryName = "ball"
let PaddleCategoryName = "paddle"
let BlockCategoryName = "block"
let GameMessageName = "gameMessage"

let BallCategory : UInt32 = 0x1 << 0
let BottomCategory : UInt32 = 0x1 << 1
let BlockCategory : UInt32 = 0x1 << 2
let PaddleCategory : UInt32 = 0x1 << 3
let BorderCategory : UInt32 = 0x1 << 4

var isFingerOnPaddle = false
var ball:SKShapeNode!
var ball:JDBallNode!

var gameWon : Bool = false {
didSet {
if(gameWon)
{
addBlock()
let holdQuene:DispatchQueue = DispatchQueue.global()
let seconds = 0.5
let delay = seconds * Double(NSEC_PER_SEC)
let dispatchTime = DispatchTime.now() + Double(Int64(delay)) / Double(NSEC_PER_SEC)
holdQuene.asyncAfter(deadline: dispatchTime, execute: {
DispatchQueue.main.async(execute: {
self.addBlock()
})
})
}

}
}

Expand All @@ -58,7 +137,8 @@ class JDBreaksScene: SKScene
var blockwidth:CGFloat = 0.0
var blockscolor:UIColor = UIColor.white

var blockscount:Int = 3
var RowCount:Int = 2
var ColumnCount:Int = 3

override func update(_ currentTime: TimeInterval) {

Expand All @@ -73,7 +153,8 @@ class JDBreaksScene: SKScene
ballcolor = configuration.ball_color
paddlecolor = configuration.paddle_color
blockscolor = configuration.block_color
blockscount = configuration.blocks_count
RowCount = configuration.RowCount
ColumnCount = configuration.ColumnCount
}

required init?(coder aDecoder: NSCoder) {
Expand All @@ -97,82 +178,50 @@ class JDBreaksScene: SKScene
self.physicsBody = borderBody

//Add Ball
ball = SKShapeNode(circleOfRadius: ballwidth/2)
ball.fillColor = ballcolor
ball.position = CGPoint(x: self.frame.width * 0.5, y: self.frame.width * 0.5)
ball.name = BallCategoryName
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.frame.width * 0.5)
ball.physicsBody?.isDynamic = true
ball.physicsBody?.friction = 0.0
ball.physicsBody?.restitution = 1.0
ball.physicsBody?.linearDamping = 0.0
ball.physicsBody?.angularDamping = 0.0
ball.physicsBody?.allowsRotation = false
ball = JDBallNode(size: CGSize(width: ballwidth, height: ballwidth), color: ballcolor)
self.addChild(ball)

//No gravity
self.physicsWorld.gravity = CGVector(dx: 0.05, dy: -0.2)
self.physicsWorld.gravity = CGVector.zero
physicsWorld.contactDelegate = self
ball.physicsBody!.applyImpulse(CGVector(dx: 2.0, dy: -2.0))

//Add Paddle
let paddlesize:CGSize = CGSize(width: paddlewidth, height: 15)
let paddle:SKShapeNode = SKShapeNode(rectOf: paddlesize, cornerRadius: 5)
let paddle:JDBreakPaddle = JDBreakPaddle(size: paddlesize, color: paddlecolor, radius: 5)
paddle.position = CGPoint(x: self.frame.width * 0.5, y: self.frame.width * 0.2)
paddle.fillColor = paddlecolor
paddle.name = PaddleCategoryName
paddle.physicsBody = SKPhysicsBody(rectangleOf: paddle.frame.size)
paddle.physicsBody?.isDynamic = false
paddle.physicsBody?.allowsRotation = true
paddle.physicsBody?.angularDamping = 0.1
paddle.physicsBody?.linearDamping = 0.1
self.addChild(paddle)

let bottomRect = CGRect(x: frame.origin.x, y: frame.origin.y, width: frame.size.width, height: 1)
let bottom = SKNode()
bottom.physicsBody = SKPhysicsBody(edgeLoopFrom: bottomRect)
addChild(bottom)

addBlock()

bottom.physicsBody!.categoryBitMask = BottomCategory
ball.physicsBody!.categoryBitMask = BallCategory
paddle.physicsBody!.categoryBitMask = PaddleCategory
borderBody.categoryBitMask = BorderCategory

borderBody.categoryBitMask = BreaksBasicSetting.BorderCategory
//
ball.physicsBody!.contactTestBitMask = BottomCategory | BlockCategory


}

func addBlock()
{
// 新增方塊
let numberOfBlocks = blockscount
let blockWidth:CGFloat = blockwidth
let totalBlocksWidth = blockWidth * CGFloat(numberOfBlocks)
let totalBlocksWidth = blockWidth * CGFloat(ColumnCount)
// 2
let xOffset = (frame.width - totalBlocksWidth) / 2
// 3
for i in 0..<numberOfBlocks {
let block = SKShapeNode(rectOf: CGSize(width: blockWidth, height: 15))
block.strokeColor = UIColor.black
block.fillColor = blockscolor
block.position = CGPoint(x: xOffset + CGFloat(CGFloat(i) + 0.5) * blockWidth,
y: frame.height * 0.8)

block.physicsBody = SKPhysicsBody(rectangleOf: block.frame.size)
block.physicsBody!.allowsRotation = false
block.physicsBody!.friction = 0.0
block.physicsBody!.affectedByGravity = false
block.physicsBody!.isDynamic = false
block.name = BlockCategoryName
block.physicsBody!.categoryBitMask = BlockCategory
block.zPosition = 2

addChild(block)
//
var FirstY:CGFloat = frame.height * 0.8
for _ in 0..<RowCount
{
for col in 0..<ColumnCount
{
let size = CGSize(width: blockWidth, height: 15)
let block = JDBreaksBrick(size: size, color: blockscolor)
block.position = CGPoint(x: xOffset + CGFloat(CGFloat(col)) * blockWidth,
y: FirstY)
block.alpha = 0.0
let fade:SKAction = SKAction.fadeAlpha(to: 1.0, duration: 2)
block.run(fade)
addChild(block)
}
FirstY -= 15
}

}

func breakBlock(node: SKNode) {
Expand All @@ -185,7 +234,6 @@ class JDBreaksScene: SKScene
particles.run(SKAction.sequence([SKAction.wait(forDuration: 1.0),
SKAction.removeFromParent()]))
}

node.removeFromParent()
}

Expand All @@ -196,13 +244,9 @@ class JDBreaksScene: SKScene
return (rand) * (to - from) + from
}

/*
This method checks to see how many bricks are left in the scene by going through all the scene’s children. For each child, it checks whether the child name is equal to BlockCategoryName. If there are no bricks left, the player has won the game and the method returns true.
*/

func isGameWon() -> Bool {
var numberOfBricks = 0
self.enumerateChildNodes(withName: BlockCategoryName) {
self.enumerateChildNodes(withName: BreaksBasicSetting.BlockCategoryName) {
node, stop in
numberOfBricks = numberOfBricks + 1 //有磚塊存在就+1

Expand All @@ -219,8 +263,9 @@ extension JDBreaksScene
let touch = touches.first
let touchLocation = touch!.location(in: self)

if let body = physicsWorld.body(at: touchLocation) {
if body.node!.name == PaddleCategoryName {
if let body = physicsWorld.body(at: touchLocation)
{
if body.node!.name == BreaksBasicSetting.PaddleCategoryName {
isFingerOnPaddle = true
}
}
Expand All @@ -235,7 +280,7 @@ extension JDBreaksScene
let touchLocation = touch!.location(in: self)
let previousLocation = touch!.previousLocation(in: self)
// 3
let paddle = childNode(withName: PaddleCategoryName) as! SKShapeNode
let paddle = childNode(withName: BreaksBasicSetting.PaddleCategoryName) as! SKShapeNode
// Take the current position and add the difference between the new and the previous touch locations.
var paddleX = paddle.position.x + (touchLocation.x - previousLocation.x)
// Before repositioning the paddle, limit the position so that the paddle will not go off the screen to the left or right.
Expand Down Expand Up @@ -270,20 +315,14 @@ extension JDBreaksScene:SKPhysicsContactDelegate
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
// 3
if firstBody.categoryBitMask == BallCategory && secondBody.categoryBitMask == BottomCategory {

}
// 球碰到磚塊
if firstBody.categoryBitMask == BallCategory && secondBody.categoryBitMask == BlockCategory {
if firstBody.categoryBitMask == BreaksBasicSetting.BallCategory && secondBody.categoryBitMask == BreaksBasicSetting.BlockCategory {
breakBlock(node: secondBody.node!)
gameWon = isGameWon()
}
}



}


7 changes: 7 additions & 0 deletions JDGamesLoading/JDGamesLoading.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import UIKit
import SpriteKit

extension UIApplication {

class func topViewController(controller: UIViewController? = UIApplication.shared.delegate?.window??.rootViewController) -> UIViewController? {
if let navigationController = controller as? UINavigationController {
return topViewController(controller: navigationController.visibleViewController)
Expand All @@ -30,6 +31,7 @@ enum GamePack
{
case Breaks
case Snacks
case PingPong
}


Expand Down Expand Up @@ -82,6 +84,11 @@ class JDLoadingViewController:UIViewController
{
skscene = JDSnackScene(size: skviewframe.size)
}
else if(GameType == .PingPong)
{
skscene = JDPingPongScene(size: skviewframe.size)
}

skview.presentScene(skscene)
}

Expand Down
Loading

0 comments on commit 88c34e7

Please sign in to comment.