Organisé pour Pacman créé sur la base des [Spécifications] publiées (https://jsai.ixsq.nii.ac.jp/ej/?action=pages_view_main&active_action=repository_view_main_item_detail&item_id=9670&item_no=1&page_id=13&block_id=23) Je veux ajouter. Faisons en sorte que Pacman contrôle non seulement en faisant glisser mais aussi par le toucher et le capteur d'accélération, et ajoutons un labyrinthe original. Le code source est disponible sur GitHub, veuillez donc vous y référer.
Ajoutez un menu de configuration pour basculer entre les opérations et les labyrinthes. Pour le labyrinthe à ajouter, je me suis référé aux spécifications suivantes en cours de développement.
Ajoutez un menu à CgSceneCreditMode. Quelques instants après l'insertion du crédit, l'entrée du menu s'affiche dans le cas 1. Si vous la touchez, vous pouvez accéder au menu.
Pour la structure de la classe CgSceneFrame, reportez-vous à la précédente [Introduction] iOS App Development # 5 [Sequence Design].
/// Credit Mode
class CgSceneCreditMode : CgSceneFrame {
enum EnEvent: Int {
case EnterConfig = 3
case Operation = 5
case ExtraMode = 6
case DebugMode = 7
case Language = 8
case ResetSetting = 9
case ExitConfig = 10
case None
}
private let table_enterConfiguration: [(Int,Int,Int,Int,EnEvent)] = [
( 26, 34, 28, 36, .EnterConfig)
]
private let table_setConfiguration: [(Int,Int,Int,Int,EnEvent)] = [
( 26, 34, 28, 36, .ExitConfig),
( 4, 25, 28, 27, .Operation),
( 4, 20, 28, 22, .ExtraMode),
( 4, 15, 28, 17, .DebugMode),
( 4, 10, 28, 12, .Language),
( 4, 5, 28, 7, .ResetSetting)
]
private var table_search: [(column0:Int,row0:Int,column1:Int,row1:Int,event:EnEvent)] = []
private var configMode: Bool = false
/// Event handler
/// - Parameters:
/// - sender: Message sender
/// - id: Message ID
/// - values: Parameters of message
override func handleEvent(sender: CbObject, message: EnMessage, parameter values: [Int]) {
if message == .Touch {
let position = CgPosition.init(x: CGFloat(values[0]), y: CGFloat(values[1]))
let event = search(column: position.column, row: position.row)
if event == .None {
if !configMode {
stopSequence()
}
} else {
goToNextSequence(event.rawValue)
}
}
}
/// Handle sequence
/// To override in a derived class.
/// - Parameter sequence: Sequence number
/// - Returns: If true, continue the sequence, if not, end the sequence.
override func handleSequence(sequence: Int) -> Bool {
switch sequence {
case 0:
configMode = false
table_search = []
clear()
printFrame()
printPlayerScore()
printHighScore()
printCredit()
printRounds()
background.print(0, color: .Orange, column: 6, row: 19, string: "PUSH START BUTTON")
background.print(0, color: .Cyan, column: 8, row: 15, string: "1 PLAYER ONLY")
if context.language == .English {
background.print(0, color: .Pink, column: 1, row: 11, string: "BONUS PAC-MAN FOR 20000 ]^_")
background.print(0, color: .Purple, column:4, row: 4, string: "@ 2020 HIWAY.KIKUTADA")
} else {
background.print(0, color: .Pink, column: 1, row: 11, string: "BONUS PAC-MAN FOR 10000 ]^_")
background.print(0, color: .Purple, column: 7, row: 7, string: "@ #$%&'()* 2020") // NAMACO
}
goToNextSequence(after: 60*16*2)
case 1:
table_search = table_enterConfiguration
background.print(0, color: .White, column: 27, row: 35, string: "$")
goToNextSequence()
case 2:
// wait for event
break;
case 3:
configMode = true
table_search = table_setConfiguration
background.fill(0, texture: 0)
printFrame()
printPlayerScore()
printHighScore()
printCredit()
background.print(0, color: .White, column: 27, row: 35, string: "#")
background.print(0, color: .Red, column: 8, row: 31, string: "CONFIGURATION")
background.print(0, color: .White, column: 4, row: 26, string: "OPERATION")
background.print(0, color: .White, column: 4, row: 21, string: "EXTRA MODE")
background.print(0, color: .White, column: 4, row: 16, string: "DEBUG MODE")
background.print(0, color: .White, column: 4, row: 11, string: "LANGUAGE")
background.print(0, color: .White, column: 4, row: 6, string: "SETTING")
print_operation(color: .Pink)
print_extraMode(color: .Pink)
print_debugMode(color: .Pink)
print_language(color: .Pink)
print_resetSetting(color: .Pink)
goToNextSequence()
case 4:
// wait for event
break;
case 5: // operation
context.operationMode = context.operationMode.getNext()
print_operation(color: .Yellow)
goToNextSequence(4)
case 6: // ExtraMode/
context.extraMode = context.extraMode.getNext()
print_extraMode(color: .Yellow)
goToNextSequence(4)
case 7: // DebugMode
context.debugMode = context.debugMode.getNext()
print_debugMode(color: .Yellow)
goToNextSequence(4)
case 8: // Language
context.language = context.language.getNext()
print_language(color: .Yellow)
goToNextSequence(4)
case 9: // ResetSetting
context.resetSetting = context.resetSetting.getNext()
print_resetSetting(color: .Yellow)
goToNextSequence(4)
case 10:
context.saveConfiguration()
goToNextSequence(0)
default:
clear()
// Stop and exit running sequence.
return false
}
return true
}
func clear() {
background.fill(0, texture: 0)
}
func print_operation(color: CgCustomBackgroundManager.EnBgColor) {
let str = context.operationMode.getString()
background.print(0, color: color, column: 16, row: 26, string: str)
}
func print_extraMode(color: CgCustomBackgroundManager.EnBgColor) {
let str = context.extraMode.getString()
background.print(0, color: color, column: 16, row: 21, string: str)
}
func print_debugMode(color: CgCustomBackgroundManager.EnBgColor) {
let str = context.debugMode.getString()
background.print(0, color: color, column: 16, row: 16, string: str)
}
func print_language(color: CgCustomBackgroundManager.EnBgColor) {
let str = context.language.getString()
background.print(0, color: color, column: 16, row: 11, string: str)
}
func print_resetSetting(color: CgCustomBackgroundManager.EnBgColor) {
let str = context.resetSetting.getString()
background.print(0, color: color, column: 16, row: 6, string: str)
}
func search(column: Int, row: Int) -> EnEvent {
var event: EnEvent = .None
for i in 0 ..< table_search.count {
let t = table_search[i]
if (t.column0 <= column && t.row0 <= row) && (t.column1 >= column && t.row1 >= row) {
event = t.event
break
}
}
return event
}
}
Lorsqu'un événement Touch est reçu par la méthode handelEvent, la plage pressée par la fonction de recherche est vérifiée et, le cas échéant, le cas de cette séquence est exécuté.
La valeur du paramètre est définie dans la classe CgContext.
class CgContext {
enum EnOperationMode: Int {
case Swipe = 0, Touch, Accel
func getString() -> String {
switch self {
case .Swipe: return "(SWIPE)"
case .Touch: return "(TOUCH)"
case .Accel: return "(ACCEL)"
}
}
func getNext() -> EnOperationMode {
switch self {
case .Swipe: return .Touch
case .Touch: return .Accel
case .Accel: return .Swipe
}
}
}
enum EnLanguage: Int {
case English = 0, Japanese
func getString() -> String {
switch self {
case .English: return "(ENGLISH) "
case .Japanese: return "(JAPANESE)"
}
}
func getNext() -> EnLanguage {
switch self {
case .English: return .Japanese
case .Japanese: return .English
}
}
}
enum EnOnOff: Int {
case Off = 0, On
func getString() -> String {
switch self {
case .On: return "(ON) "
case .Off: return "(OFF)"
}
}
func getNext() -> EnOnOff {
switch self {
case .On: return .Off
case .Off: return .On
}
}
}
enum EnSetting: Int {
case Clear = 0, Keep
func getString() -> String {
switch self {
case .Clear: return "(CLEAR)"
case .Keep: return "(KEEP) "
}
}
func getNext() -> EnSetting {
switch self {
case .Clear: return .Keep
case .Keep: return .Clear
}
}
}
var operationMode: EnOperationMode = .Swipe
var extraMode: EnOnOff = .Off
var debugMode: EnOnOff = .Off
var resetSetting: EnSetting = .Clear
var language: EnLanguage = .Japanese
//Omis ci-dessous
class GameScene: SKScene {
/// Main object with main game sequence
private var gameMain: CgGameMain!
/// Points for Swipe operation
private var startPoint: CGPoint = CGPoint.init()
private var endPoint: CGPoint = CGPoint.init()
// MotionManager for accel
private var motionManager: CMMotionManager!
override func didMove(to view: SKView) {
// Create and start game sequence.
gameMain = CgGameMain(skscene: self)
gameMain.startSequence()
// Create motion manager
motionManager = CMMotionManager()
motionManager.accelerometerUpdateInterval = 0.05
motionManager.startAccelerometerUpdates(
to: OperationQueue.current!, withHandler: {
(accelData: CMAccelerometerData?, errorOC: Error?) in self.sendAccelEvent(acceleration: accelData!.acceleration)
}
)
}
func sendAccelEvent(acceleration: CMAcceleration){
let x_diff: Int = Int(acceleration.x * 100)
let y_diff: Int = Int(acceleration.y * 100)
if abs(x_diff) > abs(y_diff) {
gameMain.sendEvent(message: .Accel, parameter: [Int(x_diff > 0 ? EnDirection.Right.rawValue : EnDirection.Left.rawValue)])
} else {
gameMain.sendEvent(message: .Accel, parameter: [Int(y_diff > 0 ? EnDirection.Up.rawValue : EnDirection.Down.rawValue)])
}
}
Générez CMMotionManager dans la classe GameScene et définissez le cycle pour obtenir la valeur dans le membre accelerometerUpdateInterval, Définissez sendAccelEvent dans la méthode de rappel.
La méthode sendAccelEvent est appelée dans un cycle de 0,05 s, dans lequel la direction est calculée à partir de l'inclinaison du capteur d'accélération, et l'événement est envoyé à l'objet avec gameMain.sendEvent de la même manière que l'opération de balayage.
class CgPlayer : CgActor {
/// Event handler
/// - Parameters:
/// - sender: Message sender
/// - id: Message ID
/// - values: Parameters of message
override func handleEvent(sender: CbObject, message: EnMessage, parameter values: [Int]) {
guard !deligateActor.isDemoMode() else { return }
switch message {
case .Accel where deligateActor.isOperationMode(mode: CgContext.EnOperationMode.Accel): fallthrough
case .Swipe where deligateActor.isOperationMode(mode: CgContext.EnOperationMode.Swipe):
if let direction = EnDirection(rawValue: values[0]) {
targetDirecition = direction
}
case .Touch where deligateActor.isOperationMode(mode: CgContext.EnOperationMode.Touch):
setTargetPosition(x: values[0], y: values[1])
targetDirecition = decideDirectionByTarget(forcedDirectionChange: true)
position.amountMoved = 0
default:
break
}
}
Si l'opération définie dans le menu de configuration est valide dans handleEvent de la classe CgPlayer (deligateActor.isOperationMode (mode: CgContext.EnOperationMode.Accel)), l'événement du capteur d'accélération est accepté.
Pour cela, veuillez vous référer à la précédente [Introduction] Développement d'applications iOS # 6 [Fonctionnement des caractères].
Faites en sorte que la méthode getMazeSource de la classe CgSceneMaze permute les données du labyrinthe par la valeur du menu. La création de ces données de labyrinthe est classique mais étonnamment facile.
func getMazeSource() -> [String] {
let mazeSource: [String] = [
"aggggggggggggjiggggggggggggb",
"e111111111111EF111111111111f",
"e1AGGB1AGGGB1EF1AGGGB1AGGB1f",
"e3E F1E F1EF1E F1E F3f",
"e1CHHD1CHHHD1CD1CHHHD1CHHD1f",
"e11111111111111111111111111f",
"e1AGGB1AB1AGGGGGGB1AB1AGGB1f",
"e1CHHD1EF1CHHJIHHD1EF1CHHD1f",
"e111111EF1111EF1111EF111111f",
"chhhhB1EKGGB1EF1AGGLF1Ahhhhd",
" e1EIHHD2CD2CHHJF1f ",
" e1EF EF1f ",
" e1EF QhUWWVhR EF1f ",
"gggggD1CD f e CD1Cggggg",
"____ 1 f e 1 ____" ,
"hhhhhB1AB f e AB1Ahhhhh",
" e1EF SggggggT EF1f ",
" e1EF EF1f ",
" e1EF AGGGGGGB EF1f ",
"aggggD1CD1CHHJIHHD1CD1Cggggb",
"e111111111111EF111111111111f",
"e1AGGB1AGGGB1EF1AGGGB1AGGB1f",
"e1CHJF1CHHHD2CD2CHHHD1EIHD1f",
"e311EF1111111 1111111EF113f",
"kGB1EF1AB1AGGGGGGB1AB1EF1AGl",
"YHD1CD1EF1CHHJIHHD1EF1CD1CHZ",
"e111111EF1111EF1111EF111111f",
"e1AGGGGLKGGB1EF1AGGLKGGGGB1f",
"e1CHHHHHHHHD1CD1CHHHHHHHHD1f",
"e11111111111111111111111111f",
"chhhhhhhhhhhhhhhhhhhhhhhhhhd"
]
let mazeSourceExtra1: [String] = [
"aggggjiggggggjiggggggjiggggb",
"e1111EF111111EF111111EF1111f",
"e1AB1EF1AGGB1CD1AGGB1EF1AB1f",
"e3EF1EF1E F1111E F1EF1EF3f",
"e1CD1CD1CHHD1AB1CHHD1CD1CD1f",
"e111111111111EF111111111111f",
"kGGB1AGGB1AGGLKGGB1AGGB1AGGl",
"YHJF1EIHD1CHHJIHHD1CHJF1EIHZ",
"e1EF1EF111111EF111111EF1EF1f",
"e1EF1EKGGGGB1EF1AGGGGLF1EF1f",
"e1CD1CHHHHHD2CD2CHHHHHD1CD1f",
"e11111111 11111111f",
"e1AB1AGGB QhUWWVhR AGGB1AB1f",
"e1EF1CHHD f e CHHD1EF1f",
"e1EF11111 f e 11111EF1f",
"kGLF1AGGB f e AGGB1EKGl",
"YHHD1EIHD SggggggT CHJF1CHHZ",
"e1111EF11 11EF1111f",
"e1AGGLF1AGGGGGGGGGGB1EKGGB1f",
"e1CHHJF1CHHHHJIHHHHD1EIHHD1f",
"e1111EF111111EF111111EF1111f",
"kGGB1EKGGGGB1EF1AGGGGLF1AGGl",
"YHHD1CHHHHHD2CD2CHHHHHD1CHHZ",
"e111111111111 111111111111f",
"e1AGGGB1AGGGGGGGGGGB1AGGGB1f",
"e1CHHJF1CHHHHJIHHHHD1EIHHD1f",
"e3111EF111111EF111111EF1113f",
"kGGB1EF1AB1AGLKGB1AB1EF1AGGl",
"YHHD1CD1EF1CHHHHD1EF1CD1CHHZ",
"e1111111EF11111111EF1111111f",
"chhhhhhhnmhhhhhhhhnmhhhhhhhd"
]
return context.extraMode == CgContext.EnOnOff.Off ? mazeSource : mazeSourceExtra1
}
Ce qui suit a été ajouté en tant qu'arrangement du jeu Pacman cette fois. --Menu de configuration --Capteur d'accélération, opération tactile
J'ai étudié la programmation iOS avec Swift basée sur les jeux de Pacman. Le code source était d'environ 5000 lignes, commentaires compris, et il était possible de réaliser facilement la qualité et l'arrangement équivalents à un jeu d'arcade.
Cela a commencé par des vacances d'été où je ne pouvais aller nulle part à Corona, mais c'était une autre bonne occasion de profiter de la programmation.
C'est la fin des 11 introductions au développement d'applications iOS.
Merci d'avoir lu ~
Recommended Posts