swift语言开发的一个游戏------熊猫跑酷(KongfuPanda)
项目地址:https://github.com/jakciehoo/KongfuPanda
欢迎加QQ群:260558552。大家一起交流iOS开发,我们可以一起学习,我很想集结一些志同道合的朋友,一起把iOS开发学好,学精,相互学习相互鼓励。
1.首先创建一个游戏项目:
2.将图片资源导入
将我项目里的
atlas整个目录
sound组里的音乐(background.mp3,fly.mp3,hit_platform.mp3,apple.mp3,hit.mp3,jump_from_platform.mp3,lose.mp3)
background组(background_f0.png,background_f1.png)
Images.xcassets的图片一个一个拷贝到相应的Images.xcassets.
3.再添加以下几个swift类
熊猫类
熊猫是我们游戏的主角,我给它添加了4个动作,跑,跳,翻滚,二次条,为了增加起跳时逼真性还添加了跑动增效动作。
//
// Panda.swift
// KongfuPanda
//
// Created by HooJackie on 15/7/1.
// Copyright (c) 2015年 jackie. All rights reserved.
// import SpriteKit
enum Status :Int{
case run = , jump, jump2,roll
} class Panda:SKSpriteNode {
//定义跑,跳,滚动等动作动画
let runAtlas = SKTextureAtlas(named: "run.atlas")
var runFrames = [SKTexture]()
let jumpAtlas = SKTextureAtlas(named: "jump.atlas")
var jumpFrames = [SKTexture]()
let rollAtlas = SKTextureAtlas(named: "roll.atlas")
var rollFrames = [SKTexture]()
//增加跳起的逼真效果动画
let jumpEffectAtlas = SKTextureAtlas(named: "jump_effect.atlas")
var jumpEffectFrames = [SKTexture]()
var jumpEffect = SKSpriteNode() var status = Status.run
var jumpStart:CGFloat = 0.0
var jumpEnd:CGFloat = 0.0 init(){ let texture = runAtlas.textureNamed("panda_run_01")
let size = texture.size()
super.init(texture: texture, color: SKColor.whiteColor(), size: size)
//跑
for var i = ; i<=runAtlas.textureNames.count; i++ {
let tempName = String(format: "panda_run_%.2d", i)
let runTexture = runAtlas.textureNamed(tempName) if (runTexture != nil) {
runFrames.append(runTexture)
}
}
//跳
for var i = ; i<=jumpAtlas.textureNames.count; i++ {
let tempName = String(format: "panda_jump_%.2d", i)
let jumpTexture = jumpAtlas.textureNamed(tempName) if (jumpTexture != nil) {
jumpFrames.append(jumpTexture)
}
}
//滚
for var i = ; i<=rollAtlas.textureNames.count; i++ {
let tempName = String(format: "panda_roll_%.2d", i)
let rollTexture = rollAtlas.textureNamed(tempName) if (rollTexture != nil) {
rollFrames.append(rollTexture)
}
}
// 跳的时候的点缀效果
for var i= ; i <= jumpEffectAtlas.textureNames.count ; i++ {
let tempName = String(format: "jump_effect_%.2d", i)
let effectexture = jumpEffectAtlas.textureNamed(tempName)
if (effectexture != nil) {
jumpEffectFrames.append(effectexture)
}
}
jumpEffect = SKSpriteNode(texture: jumpEffectFrames[])
jumpEffect.position = CGPointMake(-, -)
jumpEffect.hidden = true
self.addChild(jumpEffect) self.physicsBody = SKPhysicsBody(rectangleOfSize: size)
self.physicsBody?.dynamic = true
self.physicsBody?.allowsRotation = false
self.physicsBody?.restitution = 0.1 //反弹力
self.physicsBody?.categoryBitMask = BitMaskType.panda
self.physicsBody?.contactTestBitMask = BitMaskType.scene | BitMaskType.platform | BitMaskType.apple
self.physicsBody?.collisionBitMask = BitMaskType.platform
self.zPosition =
run() } required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
} func run(){
//清楚所有动作
self.removeAllActions()
self.status = .run
//重复跑动动作
self.runAction(SKAction.repeatActionForever(SKAction.animateWithTextures(runFrames, timePerFrame: 0.05)))
}
func jump(){
self.removeAllActions()
if status != .jump2 {
//Adds an action to the list of actions executed by the node.
//Creates an action that animates changes to a sprite’s texture. self.runAction(SKAction.animateWithTextures(jumpFrames, timePerFrame: 0.05),withKey:"jump")
//The physics body’s velocity vector, measured in meters per second.
self.physicsBody?.velocity = CGVectorMake(, )
if status == Status.jump {
self.runAction(SKAction.animateWithTextures(rollFrames, timePerFrame: 0.05))
status = Status.jump2
self.jumpStart = self.position.y
}else {
showJumpEffect()
status = .jump
}
} }
func roll(){
self.removeAllActions()
self.status = .roll
self.runAction(SKAction.animateWithTextures(rollFrames, timePerFrame: 0.05),completion:{
self.run()
})
} func showJumpEffect(){
jumpEffect.hidden = false
var ectAct = SKAction.animateWithTextures( jumpEffectFrames, timePerFrame: 0.05)
var removeAct = SKAction.runBlock({() in
self.jumpEffect.hidden = true
})
// 执行两个动作,先显示,后隐藏
jumpEffect.runAction(SKAction.sequence([ectAct,removeAct]))
} }
Panda.swift
平台类
//
// Platform.swift
// KongfuPanda
//
// Created by HooJackie on 15/7/1.
// Copyright (c) 2015年 jackie. All rights reserved.
// import SpriteKit class Platform:SKNode {
var width:CGFloat = 0.0
var height:CGFloat = 10.0
var isDown = false
var isShock = false
//创建平台
func onCreate(arrSprite:[SKSpriteNode]){
for platform in arrSprite {
platform.position.x = self.width
self.addChild(platform)
self.width += platform.size.width
}
//短到只有三小块的平台会下落
if arrSprite.count <= {
isDown = true
}else {
//随机振动
let random = arc4random() %
if random > {
isShock = true
}
}
self.height = 10.0 self.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(self.width, self.height),center:CGPointMake(self.width/, ))
self.physicsBody?.categoryBitMask = BitMaskType.platform
self.physicsBody?.dynamic = false
self.physicsBody?.allowsRotation = false
self.physicsBody?.restitution =
self.zPosition = } }
Platform.swift
平台生成类
难点1:在理解平台如何生成。可以查看资源图platform_l ,platform_m,platform_r.将他们拼接到一起,根据Platfom_m的数量不同,产生不同的长度的平台。
难点2:游戏中的熊猫移动我们眼睛看以为是熊猫在跑,其实移动的是平台,通过平台向左移动,给我们的错觉是熊猫在向右跑。
//
// PlatformFactory.swift
// KongfuPanda
//
// Created by HooJackie on 15/7/1.
// Copyright (c) 2015年 jackie. All rights reserved.
// import SpriteKit class PlatformFactory:SKNode {
let textureLeft = SKTexture(imageNamed: "platform_l")
let textureMid = SKTexture(imageNamed: "platform_m")
let textureRight = SKTexture(imageNamed: "platform_r") var platforms = [Platform]()
var screenWdith:CGFloat = 0.0
var delegate:ProtocolMainscreen? // 随机生成一定长度的平台
func createPlatformRandom(){
let midNum = arc4random()% +
let gap:CGFloat = CGFloat(arc4random()% + )
let x = self.screenWdith + CGFloat(midNum*) + gap +
let y = CGFloat(arc4random()% + ) createPlatform(midNum, x: x, y: y)
}
//生成平台方法
func createPlatform(midNum:UInt32,x:CGFloat,y:CGFloat){
let platform = Platform()
let platform_left = SKSpriteNode(texture: textureLeft)
platform_left.anchorPoint = CGPointMake(, 0.9) let platform_right = SKSpriteNode(texture: textureRight)
platform_right.anchorPoint = CGPointMake(, 0.9) var arrPlatform = [SKSpriteNode]() arrPlatform.append(platform_left)
platform.position = CGPointMake(x, y) for i in ...midNum {
let platform_mid = SKSpriteNode(texture: textureMid)
platform_mid.anchorPoint = CGPointMake(, 0.9)
arrPlatform.append(platform_mid)
}
arrPlatform.append(platform_right)
platform.onCreate(arrPlatform)
platform.name = "platform"
self.addChild(platform) platforms.append(platform)
self.delegate?.onGetData(platform.width + x - screenWdith,theY:y) }
//平台向左移动的方法
func move(speed:CGFloat){
for p in platforms {
let position = p.position
p.position = CGPointMake(position.x - speed, position.y)
}
if platforms[].position.x < -platforms[].width{
platforms[].removeFromParent()
platforms.removeAtIndex()
}
}
//清楚所有的Node
func reset(){ self.removeAllChildren()
platforms.removeAll(keepCapacity: false)
}
}
PlatformFactory.swift
背景音乐类
生成各种音效。
//
// BackGround.swift
//场景的动态背景图类
// KongfuPanda
//
// Created by HooJackie on 15/7/1.
// Copyright (c) 2015年 jackie. All rights reserved.
// import SpriteKit class Background:SKNode {
//近处的背景
var arrBG = [SKSpriteNode]()
//远处的背景
var arrFar = [SKSpriteNode]() override init() {
super.init()
var farTexture = SKTexture(imageNamed: "background_f1")
var farBg0 = SKSpriteNode(texture: farTexture)
farBg0.position.y =
farBg0.zPosition =
farBg0.anchorPoint = CGPointMake(, ) var farBg1 = SKSpriteNode(texture: farTexture)
farBg1.position.y =
farBg1.zPosition =
farBg1.anchorPoint = CGPointMake(, )
farBg1.position.x = farBg1.frame.width var farBg2 = SKSpriteNode(texture: farTexture)
farBg2.position.y =
farBg2.zPosition =
farBg2.anchorPoint = CGPointMake(, )
farBg2.position.x = farBg2.frame.width* self.addChild(farBg0)
self.addChild(farBg1)
self.addChild(farBg2)
arrFar.append(farBg0)
arrFar.append(farBg1)
arrFar.append(farBg2) var texture = SKTexture(imageNamed: "background_f0")
var bg0 = SKSpriteNode(texture: texture)
bg0.anchorPoint = CGPointMake(, )
bg0.position.y =
bg0.zPosition = var bg1 = SKSpriteNode(texture: texture)
bg1.anchorPoint = CGPointMake(, )
bg1.position.y =
bg1.zPosition =
bg1.position.x = bg0.frame.size.width
self.addChild(bg0)
self.addChild(bg1)
arrBG.append(bg0)
arrBG.append(bg1)
} required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
} func move(speed:CGFloat){
//近景
for bg in arrBG {
bg.position.x -= speed
}
if arrBG[].position.x + arrBG[].frame.size.width < speed {
arrBG[].position.x =
arrBG[].position.x = arrBG[].frame.size.width
}
//远景
for far in arrFar {
far.position.x -= speed/ }
if arrFar[].position.x + arrFar[].frame.size.width < speed/ {
arrFar[].position.x =
arrFar[].position.x = arrFar[].frame.size.width
arrFar[].position.x = arrFar[].frame.size.width *
} } }
BackGround.swift
位运算标识类
//
// BitMaskType.swift
// KongfuPanda
//
// Created by HooJackie on 15/7/1.
// Copyright (c) 2015年 jackie. All rights reserved.
// class BitMaskType {
class var panda:UInt32 {
return <<
}
class var platform:UInt32 {
return <<
}
class var apple:UInt32 {
return <<
}
class var scene:UInt32{
return <<
}
}
BitMaskType.swift
苹果生成类
import SpriteKit class AppleFactory:SKNode{
let appleTexture = SKTexture(imageNamed: "apple")
var sceneWidth:CGFloat = 0.0
var arrApple = [SKSpriteNode]()
var timer = NSTimer()
var theY:CGFloat = 0.0 override init() {
super.init()
} required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func onInit(width:CGFloat, y:CGFloat) { self.sceneWidth = width
self.theY = y
timer = NSTimer.scheduledTimerWithTimeInterval( 0.2, target: self, selector: "createApple", userInfo: nil, repeats: true)
}
func createApple(){
var random = arc4random() %
if random > {
var apple = SKSpriteNode(texture: appleTexture)
apple.physicsBody = SKPhysicsBody(rectangleOfSize: apple.size)
apple.physicsBody!.restitution =
apple.physicsBody!.categoryBitMask = BitMaskType.apple
apple.physicsBody!.dynamic = false
apple.anchorPoint = CGPointMake(, )
apple.zPosition =
apple.position = CGPointMake(sceneWidth+apple.frame.width , theY + )
arrApple.append(apple)
self.addChild(apple)
} }
func move(speed:CGFloat){
for apple in arrApple {
apple.position.x -= speed
}
if arrApple.count > && arrApple[].position.x < -{ arrApple[].removeFromParent()
arrApple.removeAtIndex() } }
func reSet(){
self.removeAllChildren()
arrApple.removeAll(keepCapacity: false)
}
}
AppleFactory
游戏主界面类
import SpriteKit class GameScene: SKScene,SKPhysicsContactDelegate , ProtocolMainscreen{
lazy var panda = Panda()
lazy var platformFactory = PlatformFactory()
lazy var sound = SoundManager()
lazy var bg = Background()
lazy var appleFactory = AppleFactory()
let scoreLab = SKLabelNode(fontNamed:"Chalkduster")
let appLab = SKLabelNode(fontNamed:"Chalkduster")
let myLabel = SKLabelNode(fontNamed:"Chalkduster")
var appleNum = var moveSpeed :CGFloat = 15.0
var maxSpeed :CGFloat = 50.0
var distance:CGFloat = 0.0
var lastDis:CGFloat = 0.0
var theY:CGFloat = 0.0
var isLose = false
override func didMoveToView(view: SKView) { let skyColor = SKColor(red:113.0/255.0, green:197.0/255.0, blue:207.0/255.0, alpha:1.0)
self.backgroundColor = skyColor
scoreLab.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Left
scoreLab.position = CGPointMake(, self.frame.size.height-)
scoreLab.text = "run: 0 km"
self.addChild(scoreLab) appLab.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Left
appLab.position = CGPointMake(, self.frame.size.height-)
appLab.text = "eat: \(appleNum) apple"
self.addChild(appLab) myLabel.text = "";
myLabel.fontSize = ;
myLabel.zPosition =
myLabel.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame));
self.addChild(myLabel) self.physicsWorld.contactDelegate = self
self.physicsWorld.gravity = CGVectorMake(, -)
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsBody!.categoryBitMask = BitMaskType.scene
self.physicsBody!.dynamic = false panda.position = CGPointMake(, )
self.addChild(panda)
self.addChild(platformFactory)
platformFactory.screenWdith = self.frame.width
platformFactory.delegate = self
platformFactory.createPlatform(, x: , y: ) self.addChild(bg) self.addChild(sound)
sound.playBackgroundMusic() appleFactory.onInit(self.frame.width, y: theY)
self.addChild( appleFactory ) }
func didBeginContact(contact: SKPhysicsContact){ //熊猫和苹果碰撞
if (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask) == (BitMaskType.apple | BitMaskType.panda){
sound.playEat()
self.appleNum++
if contact.bodyA.categoryBitMask == BitMaskType.apple {
contact.bodyA.node!.hidden = true
}else{
contact.bodyB.node!.hidden = true
} } //熊猫和台子碰撞
if (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask) == (BitMaskType.platform | BitMaskType.panda){
var isDown = false
var canRun = false
if contact.bodyA.categoryBitMask == BitMaskType.platform {
if (contact.bodyA.node as! Platform).isDown {
isDown = true
contact.bodyA.node!.physicsBody!.dynamic = true
contact.bodyA.node!.physicsBody!.collisionBitMask =
}else if (contact.bodyA.node as! Platform).isShock {
(contact.bodyA.node as! Platform).isShock = false
downAndUp(contact.bodyA.node!, down: -, downTime: 0.2, up: , upTime: , isRepeat: true)
}
if contact.bodyB.node!.position.y > contact.bodyA.node!.position.y {
canRun=true
} }else if contact.bodyB.categoryBitMask == BitMaskType.platform {
if (contact.bodyB.node as! Platform).isDown {
contact.bodyB.node!.physicsBody!.dynamic = true
contact.bodyB.node!.physicsBody!.collisionBitMask =
isDown = true
}else if (contact.bodyB.node as! Platform).isShock {
(contact.bodyB.node as! Platform).isShock = false
downAndUp(contact.bodyB.node!, down: -, downTime: 0.2, up: , upTime: , isRepeat: true)
}
if contact.bodyA.node!.position.y > contact.bodyB.node!.position.y {
canRun=true
} } panda.jumpEnd = panda.position.y
if panda.jumpEnd-panda.jumpStart <= - {
panda.roll()
sound.playRoll() if !isDown {
downAndUp(contact.bodyA.node!)
downAndUp(contact.bodyB.node!)
} }else{
if canRun {
panda.run()
} }
} if (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask) == (BitMaskType.scene | BitMaskType.panda) {
println("game over")
myLabel.text = "game over";
sound.playDead()
isLose = true
sound.stopBackgroundMusic() } //落地后jumpstart数据要设为当前位置,防止自由落地计算出错
panda.jumpStart = panda.position.y
}
func didEndContact(contact: SKPhysicsContact){
panda.jumpStart = panda.position.y }
func downAndUp(node :SKNode,down:CGFloat = -,downTime:CGFloat=0.05,up:CGFloat=,upTime:CGFloat=0.1,isRepeat:Bool=false){
let downAct = SKAction.moveByX(, y: down, duration: Double(downTime))
//moveByX(CGFloat(0), y: down, duration: downTime)
let upAct = SKAction.moveByX(, y: up, duration: Double(upTime))
let downUpAct = SKAction.sequence([downAct,upAct])
if isRepeat {
node.runAction(SKAction.repeatActionForever(downUpAct))
}else {
node.runAction(downUpAct)
} } override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
if isLose {
reSet()
}else{
if panda.status != Status.jump2 {
sound.playJump()
}
panda.jump()
} }
//重新开始游戏
func reSet(){
isLose = false
panda.position = CGPointMake(, )
myLabel.text = ""
moveSpeed = 15.0
distance = 0.0
lastDis = 0.0
self.appleNum =
platformFactory.reset()
appleFactory.reSet()
platformFactory.createPlatform(, x: , y: )
sound.playBackgroundMusic()
}
override func update(currentTime: CFTimeInterval) {
if isLose { }else{
if panda.position.x < {
var x = panda.position.x +
panda.position = CGPointMake(x, panda.position.y)
}
distance += moveSpeed
lastDis -= moveSpeed
var tempSpeed = CGFloat( + Int(distance/))
if tempSpeed > maxSpeed {
tempSpeed = maxSpeed
}
if moveSpeed < tempSpeed {
moveSpeed = tempSpeed
} if lastDis < {
platformFactory.createPlatformRandom()
}
distance += moveSpeed
scoreLab.text = "run: \(Int(distance/1000*10)/10) km"
appLab.text = "eat: \(appleNum) apple"
platformFactory.move(moveSpeed)
bg.move(moveSpeed/)
appleFactory.move(moveSpeed)
} } func onGetData(dist:CGFloat,theY:CGFloat){ self.lastDis = dist
self.theY = theY
appleFactory.theY = theY
} } protocol ProtocolMainscreen {
func onGetData(dist:CGFloat,theY:CGFloat)
}
GameScene.swift
4.最后的游戏的效果图:
swift语言开发的一个游戏------熊猫跑酷(KongfuPanda)的更多相关文章
- 使用 Go 语言开发大型 MMORPG 游戏服务器怎么样?(非常稳定、捕获所有异常、非常适合从头开始,但大公司已经有现成的C++框架、所以不会使用)
使用 Go 语言开发大型 MMORPG 游戏服务器怎么样?和C Socket服务器比起来有什么优劣?可行性怎么样? 从2013年起,经朋友推荐开始用Golang编写游戏登陆服务器, 配合C++做第三方 ...
- 基于Swift语言开发微信、QQ和微博的SSO授权登录代码分析
前言 Swift 语言,怎么说呢,有一种先接受后排斥.又欢迎的感觉,纵观国外大牛开源框架或项目演示,Swift差点儿占领了多半,而国内尽管出现非常多相关技术介绍和教程,可是在真正项目开发中使用的占领非 ...
- Go语言开发第一个Hello,World
在网上看到go语言的各种评价,也是闻名已久,但是没有自己实践过,也不知道它的好,它的坏,今天就来试试第一个小程序 第一步.如何下载 1)下载go安装程序 下载地址:https://golang.org ...
- IOS Swift语言开发 tableView的重用以及自cell的自适应高度
http://www.aichengxu.com/iOS/11143168.htm 一.准备数据 (这是一个元组,第一个元素为英雄的名字;第二个元素为英雄头像图片的名字,格式为.PNG,如果为其他的格 ...
- 【iOS开发】如何用 Swift 语言进行LBS应用的开发?
本文分为三部分,第一部分详解用Swift语言开发LBS应用,并给出完整的示例与源代码:第二部分介绍如何申请LBS密钥,第三部分是综合示例查看,扫描二维码即可查看示例demo. 第一部分 使用Swift ...
- 开发H5小游戏
Egret白鹭H5小游戏开发入门(一) 前言: 好久没更新博客了,以前很多都不会,所以常常写博客总结,倒是现在有点点经验了就懒了.在过去的几个月里,在canvas游戏框架方面,撸过了CreateJ ...
- 苹果新的编程语言 Swift 语言进阶(一)--综述
Swift 是苹果开发和提供的供开发IOS 和OS X应用的一门新的语言.Swift语言基于C 和Objective-C语言,除了提供C 和Objective-C语言具有的所有语法功能外,为了编程方便 ...
- 苹果新的编程语言 Swift 语言进阶(五)--控制流
Swift 语言支持C语言全部的控制语句.包含for 和while循环语句,if和switch条件语句,以及break和continue控制语句等. Swift 语言除了支持以上语句,还添加了一个f ...
- 用C++语言开发Android程序 配置开发环境
转自:http://www.cnblogs.com/yaotong/p/3622430.html 用C++语言开发Android程序 配置开发环境 如果你是一个C++语言的死忠,你喜欢C++语言到 ...
随机推荐
- js倒计时 网上流传最多的
<!DOCTYPE html><html><head><script src="http://libs.baidu.com/jquery/1.10. ...
- js时间差转为天数
function DateDiff(sDate1, sDate2){ //sDate1和sDate2是2006-12-18格式 var aDate, oDate1, oDate2, iDays aDa ...
- canvas实现绘画
html代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...
- AngularJS 中文资料+工具+库+Demo 大搜集
中文学习资料: 中文资料且成系统的就这么多,优酷上有个中文视频. http://www.cnblogs.com/lcllao/archive/2012/10/18/2728787.html 翻译的 ...
- Linux基础: 网络命令和进程管理
netstat lsof ps pstree pkill/kill (了解jenkins git,排查环境) 查询服务器之间是否有链接(netstat -an) 某个服务是否启动(了解服务对应的 ...
- 更准确的mysql全文索引
MYSQL自带的全文索引在查找数据的时候,有非常多的限制,如字符少于3个不能搜索,常用字不能搜索 但mysql 的like进行查询的时候又非常的慢 但你需要用到比较准确的查询的时候,要么不用mysql ...
- SDWebImage源码刨根问底
前言: SDWebImage是iOS中一款处理图片的框架, 使用它提供的方法, 一句话就能让UIImageView,自动去加载并显示网络图片,将图片缓存到内存或磁盘缓存,正好有阅读开源项目的计划,于是 ...
- MVC之视图的布局
1. RenderBody 布局在Razor引擎中没有了“母版页”,取而代之的是叫做“布局”的页面(_Layout.cshtml)放在了共享视图文件夹中.在这个页面中,会看到标签里有这样一条语句 ...
- springmvc:BeanNameViewResolver访问内部资源视图对象和访问外部资源视图对象
<!-- 处理器映射器 --> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerM ...
- Objective-C:Block
Block是OC中一种与其它语言的语法区别较大的一种用法,需要注意: Block也叫代码段,它封装了一段代码,可以在任何时候执行: Block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数 ...