Bonjour, Habr! À une certaine époque, les articles «voici mon premier jeu» étaient très populaires ici. Récemment, je ne les ai pas vus, j'ai donc décidé de combler cette lacune moi-même.
Histoire de la création et du gameplay
Je voulais faire un jeu créé indépendamment du début à la fin depuis longtemps - j'ai commencé en 2012 avec un jeu de tir descendant sur java pour Android. Ayant rapidement réalisé qu'il était impossible de le tirer seul, après quelques années, je suis passé à une stratégie miniature en C ++. Au bout d'un an environ, l'intérêt pour elle a également disparu, et bien que je revienne parfois sur ces projets, je me suis sérieusement rendu compte que je ne les finirais jamais. Et puis j'ai lu beaucoup d'articles pour les nouveaux venus sur gamedev et j'ai décidé d'emprunter le chemin de la moindre résistance: cloner rapidement quelque chose de connu. Seul un tel chemin permettrait enfin d'amener au moins quelque chose à une fin logique.
Le jeu Threes a été pris comme base, ou plutôt son clone 2048, dans lequel j'étais alors très coincé. Comme caractéristique originale, il a été décidé de rendre le champ non carré, mais hexagonal. Et aussi avec la possibilité de choisir sa taille. Et pour le rendre complètement différent de Threes ou 2048, rendez dynamique le principe de la combinaison de cellules - l'utilisateur est libre de choisir s'il aime conduire des triples ou des puissances de deux.
, , , . : 33, 77 (, , , , ). , scrum- . : 1, 2, 3, 5, 8 ( , ).
" !", , . : 1 "" 2, . 8 , .
, . ", ?" - . .
, ? , ! , ( ). , . : , , . , , . , , .
, . , Model - ViewController - Command, , - , . , . swift C# . , , , , , , . , Swift , , , .
, . , , motion blur, haptic feedback, , , , , ( ), app store , -, ffmpeg' , privacy policy, , - , -, , . , 238 . , , .
, ( , ). , . , .
- , .
, , .
, , qBasic. : , , - . , , . , . : XUp, XDown, YUp, YDown, Left and Right, , . :
class BaseCellsIterator {
internal var line = LineCellsContainer() //
internal var x: Int = 0
internal var y: Int = 0
internal var w: Int { self.gameModel.field.width } //
internal var h: Int { self.gameModel.field.height } //
}
class MoveXDownIterator: BaseCellsIterator, CellsIterator {
func next() -> LineCellsContainer? {
line.clear() //
if x >= w { // "" ,
x = 0
y += 1
}
if y >= h { // "" , ,
return nil
}
// for(; x <= w; x++) ""
for _ in x ..< w {
defer { x += 1 }
guard let cell = getCell(x, y),
!cell.isBlocked,
!cell.isBlockedFromSwipe
else { break } // ,
line.add(cell)
}
return line
}
}
. , - , . , , - ( , placeholder'). , , , . .
- , - . , SpriteKit , , , , . SKNode , ( - , - , ), :
public func renderNode(node: SKNode, filename: String) throws {
let destinationURL = URL(fileURLWithPath: filename, isDirectory: false) as CFURL
guard let texture = view.texture(from: node) else { throw ImageGeneratorError.textureRenderFailed }
let image = texture.cgImage()
// "public.png" Uniform Type Identifier, , , .
guard let destination = CGImageDestinationCreateWithURL(destinationURL, "public.png" as CFString, 1, nil) else { throw ImageGeneratorError.destinationCreationFailed }
let imageProperties = [kCGImageDestinationLossyCompressionQuality as String: 0.8]
CGImageDestinationAddImage(destination, image,imageProperties as CFDictionary)
let result = CGImageDestinationFinalize(destination)
let date = Date()
let calendar = Calendar.current
let hour = calendar.component(.hour, from: date)
let minutes = calendar.component(.minute, from: date)
let time = "\(hour):\(minutes)"
print(result
? "\(filename) rendered successfully at \(time)"
: "\(filename) render FAILED at \(time)")
}
: , - , . , .
- - App Store, , . - 37 , 6 . . -, .
, , , - , , - - . , , . - , - . .
:
.
. , Swift #8/9.
. , , . (" ") .
, full-stack , ios-. , , , " .net, Swift" .
Et le résultat le plus important est que maintenant j'ai enfin un jeu qui m'intéresse personnellement de monter dans le train en rentrant du travail. C'est dommage, je travaille depuis chez moi depuis un an maintenant.