作りやすそうなところをまず着手。
spin ボタンを何度も押せてしまうという現象があり、これはまずい。 @State 変数 isSpin を作って、ドラムの回転状況を保存。 初期値は false すなわち回転していない。 false の時は spin ボタンを押せるように、.disable() に記載。 また、stop ボタンも同様に、isSpin の状態に応じて色をかえる。
変数 isSpin の値を変えるのは spin ボタン及び stop ボタンの method が起動したとき。
という考えでソース改訂。うまくいった。
import SwiftUI
struct ContentView: View {
// 定数なので let 変数なら var
static let aMinimumCharacterSet = [ "🍒", "🍉", "🩷", "🔔"]
var aReelOne: [ String ] {
ContentView.aMinimumCharacterSet + ContentView.aMinimumCharacterSet
}
static let symbolHeight: CGFloat = 120.0
private var initialYOffset: CGFloat {
( CGFloat( aReelOne.count ) - 3 ) * ContentView.symbolHeight / 2 * -1
}
@State private var yOffset: CGFloat = 0
// ? は optional 型指定、nil 許容。覚えにくいなぁ
@State var timer: Timer? = nil
// private: そこでしか使えない
// static: そのクラスでしか使えない
@State var isSpin = false
var body: some View {
VStack( spacing: 40 ) {
Text( "スロットマシーン" )
.padding()
ZStack {
// 背景の黒い枠(3コマ分の高さ)
RoundedRectangle( cornerRadius: 20 )
.fill( Color(white: 0.15 ))
.frame( width: 160, height: 360 )
.overlay(
VStack {
Spacer()
Rectangle()
.fill( Color.red.opacity( 0.4 ))
.frame( height: 4 )
Spacer()
}
)
.overlay(
RoundedRectangle( cornerRadius: 20 )
.stroke( Color.yellow, lineWidth: 5 )
)
VStack( spacing: 0 ){
ForEach( 0 ..< aReelOne.count, id: \.self ){ index in
Text( aReelOne[ index ] )
.font( .system( size: 75 ))
.frame( width: 160, height: ContentView.symbolHeight, alignment: .center )
}
}
.onAppear { yOffset = initialYOffset }
.offset( y: yOffset )
} //ZStack
.frame( width: 160, height: 360 )
.clipped()
Text( "状態" )
.font( .headline )
.foregroundColor( .black )
.frame( height: 30 )
.padding()
}
HStack( spacing: 30 ) {
Button( action: { startSpin() }) {
Text( "Spin" )
.font( .headline ).bold()
.padding()
.frame( width: 140 )
.background( isSpin ? Color.gray : Color.yellow )
.foregroundColor( .black )
.cornerRadius( 10 )
}
.disabled( isSpin )
Button( action: { stopSpin() }) {
Text( "Stop" )
.font( .headline ).bold()
.padding()
.frame( width: 140 )
.background( isSpin ? Color.yellow : Color.gray )
.foregroundColor( .black )
.cornerRadius( 10 )
}
.disabled( !isSpin )
} // HStack
} // body
func startSpin() {
timer = Timer.scheduledTimer( withTimeInterval: 0.01, repeats: true ) {
_ in
yOffset += 10
if yOffset > ContentView.symbolHeight {
yOffset = initialYOffset - 40
} // end of if
} // end of timer
isSpin.toggle()
} // end of startSpin()
func stopSpin(){
timer?.invalidate()
timer = nil
isSpin.toggle()
} // end of stopSpin()
} // struct
#Preview {
ContentView()
}
このほか更新が必要なのは次の通り。
- ドラムの絵柄と回転スピードを本物に合わせる。ガイドラインがあるはずなので調べよう。
- 絵柄がぴったりの位置で止まらず、途中の位置で止まる。実物のスロットマシーンは途中で止まらないので改良が必要。
- 当たりフラグが立たないと特定の絵柄を止められない。例えばチェリーフラグが立って初めてチェリーを止めることができる。当たりフラグが立っていないならドラムを滑らせ表示外にする。