Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hugo/feature/Add Xylophone #504

Merged
merged 1 commit into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Leka - iOS Monorepo
# Copyright 2023 APF France handicap
# SPDX-License-Identifier: Apache-2.0

id: cd5d93afbd8f4071b25479cd6372a7a9
name: Xylophone Heptatonic
description: L'objectif est de jouer de la musique à l'aide du xylophone
image: activity_color_recognition_1
sequence:
- exercises:
- instructions: Joue du xylophone avec Leka
interface: musicalInstruments
payload:
instrument: xylophone
scale: majorHeptatonic
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Leka - iOS Monorepo
# Copyright 2023 APF France handicap
# SPDX-License-Identifier: Apache-2.0

id: 264d720bf8904043b97d5d7b3d0e7124
name: Xylophone Pentatonic
description: L'objectif est de jouer de la musique à l'aide du xylophone
image: activity_color_recognition_1
sequence:
- exercises:
- instructions: Joue du xylophone avec Leka
interface: musicalInstruments
payload:
instrument: xylophone
scale: majorPentatonic
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ let kActivities: [Activity] = [
ContentKit.decodeActivity("remote-standard"),
ContentKit.decodeActivity("remote-arrow"),
ContentKit.decodeActivity("activity-hideAndSeek"),
ContentKit.decodeActivity("activity-xylophone-pentatonic"),
ContentKit.decodeActivity("activity-xylophone-heptatonic"),
]

struct GEKNewSystemView: View {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Leka - iOS Monorepo
// Copyright 2023 APF France handicap
// SPDX-License-Identifier: Apache-2.0

public enum MusicalInstrument {

public struct Payload: Codable {
public let instrument: String
public let scale: String

enum CodingKeys: String, CodingKey {

Check failure on line 11 in Modules/ContentKit/Sources/Exercise/Exercice+MusicalInstrument.swift

View workflow job for this annotation

GitHub Actions / lint

Types should be nested at most 1 level deep (nesting)

Check failure on line 11 in Modules/ContentKit/Sources/Exercise/Exercice+MusicalInstrument.swift

View workflow job for this annotation

GitHub Actions / lint

Types should be nested at most 1 level deep (nesting)
case instrument, scale
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)

self.instrument = try container.decode(String.self, forKey: .instrument)
self.scale = try container.decode(String.self, forKey: .scale)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ extension Exercise {
case remoteStandard
case remoteArrow
case hideAndSeek
case musicalInstruments
}

}
1 change: 1 addition & 0 deletions Modules/ContentKit/Sources/Exercise/Exercise+Payload.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ extension DragAndDropIntoZones.Payload: ExercisePayloadProtocol {}
extension DragAndDropToAssociate.Payload: ExercisePayloadProtocol {}
extension AudioRecordingPlayer.Payload: ExercisePayloadProtocol {}
extension HideAndSeek.Payload: ExercisePayloadProtocol {}
extension MusicalInstrument.Payload: ExercisePayloadProtocol {}
3 changes: 3 additions & 0 deletions Modules/ContentKit/Sources/Exercise/Exercise.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ public struct Exercise: Codable {
case (.hideAndSeek, .none):
payload = try container.decode(HideAndSeek.Payload.self, forKey: .payload)

case (.musicalInstruments, .none):
payload = try container.decode(MusicalInstrument.Payload.self, forKey: .payload)

case (.remoteStandard, .none),
(.remoteArrow, .none):
payload = nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@

import AudioKit
import Combine
import ContentKit
import SwiftUI

public class MelodyGameplay: ObservableObject {
@Published public var progress: CGFloat = 0.0
@Published var state: ExerciseState = .idle

private let xyloPlayer = MIDIPlayer(name: "Xylophone", samples: xyloSamples)
private let xyloPlayer = MIDIPlayer(instrument: .xylophone)

private let song: MelodySongModel

Expand All @@ -25,7 +26,7 @@
self.midiNotes = xyloPlayer.getMidiNotes()
self.currentNoteNumber = midiNotes[currentNoteIndex].noteNumber - song.octaveGap

// TODO(@ladislas): Light on Leka lights with the following color getter

Check failure on line 29 in Modules/GameEngineKit/Sources/Staging/Melody/MelodyGameplay.swift

View workflow job for this annotation

GitHub Actions / lint

TODOs should be resolved ((@ladislas): Light on Leka lig...) (todo)
print(getColorFromMIDINote())
}

Expand All @@ -52,7 +53,7 @@
print("Replay song")
self.xyloPlayer.play()

// TODO(@hugo): BUG - length is not correct, it returns 32 seconds but the track is ~12 secondes long

Check failure on line 56 in Modules/GameEngineKit/Sources/Staging/Melody/MelodyGameplay.swift

View workflow job for this annotation

GitHub Actions / lint

TODOs should be resolved ((@hugo): BUG - length is not c...) (todo)
DispatchQueue.main.asyncAfter(deadline: .now() + self.xyloPlayer.getDuration()) {
print("Reset UI")
self.state = .completed
Expand All @@ -68,6 +69,6 @@
let index = kListOfTiles.firstIndex(where: {
$0.noteNumber == currentNoteNumber
})
return kListOfTiles[index!].color
return kListOfTiles[index!].color.screen
}
}
17 changes: 13 additions & 4 deletions Modules/GameEngineKit/Sources/Staging/Melody/MelodyView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@
// Copyright 2023 APF France handicap
// SPDX-License-Identifier: Apache-2.0

import DesignKit
import AudioKit
import RobotKit
import SwiftUI

public struct XylophoneTile: Identifiable {
public var id: Int
var noteNumber: MIDINoteNumber
var color: Robot.Color
}

public let kListOfTiles: [XylophoneTile] = [
XylophoneTile(id: 0, noteNumber: 24, color: .pink),
XylophoneTile(id: 1, noteNumber: 26, color: .red),
Expand All @@ -19,7 +26,7 @@ public struct MelodyView: View {
@ObservedObject private var viewModel: MelodyViewModel

let defaultTilesSpacing: CGFloat = 16
let tilesNumber = 7
let tileNumber = 7

public init(gameplay: MelodyGameplay) {
self.viewModel = MelodyViewModel(gameplay: gameplay)
Expand All @@ -36,9 +43,11 @@ public struct MelodyView: View {
Button {
viewModel.onTileTapped(tile: tile)
} label: {
tile.color
tile.color.screen
}
.buttonStyle(XylophoneTileButtonStyle(index: tile.id, tilesNumber: tilesNumber))
.buttonStyle(
MusicalInstrumentView.XylophoneView.TileButtonStyle(index: tile.id, tileNumber: tileNumber)
)
.compositingGroup()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class MelodyViewModel: Identifiable, ObservableObject {
public var gameplay: MelodyGameplay

@Published public var progress: CGFloat
@Published var state: ExerciseState
@Published var state: ExerciseState

private var cancellables: Set<AnyCancellable> = []

Expand Down

This file was deleted.

80 changes: 0 additions & 80 deletions Modules/GameEngineKit/Sources/Staging/XylophoneTile.swift

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Leka - iOS Monorepo
// Copyright 2023 APF France handicap
// SPDX-License-Identifier: Apache-2.0

import AudioKit
import DesignKit
import RobotKit
import SwiftUI

extension MusicalInstrumentView.XylophoneView {

struct TileButtonStyle: ButtonStyle {
let xyloAttachColor = Color(red: 0.87, green: 0.65, blue: 0.54)
let defaultMaxTileHeight: Int = 500
let defaultTileHeightGap: Int = 250
let defaultTileWidth: CGFloat = 130
let defaultTilesScaleFeedback: CGFloat = 0.98
let defaultTilesRotationFeedback: CGFloat = -1

let index: Int
let tileNumber: Int

func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.overlay {
VStack {
Spacer()
Circle()
.fill(xyloAttachColor)
.shadow(
color: .black.opacity(0.4),
radius: 3, x: 0, y: 3
)
Spacer()
Circle()
.fill(xyloAttachColor)
.shadow(
color: .black.opacity(0.4),
radius: 3, x: 0, y: 3
)
Spacer()
}
.frame(width: 44)
}
.overlay {
RoundedRectangle(cornerRadius: 7, style: .circular)
.stroke(.black.opacity(configuration.isPressed ? 0.3 : 0), lineWidth: 20)
}
.clipShape(RoundedRectangle(cornerRadius: 7, style: .circular))
.frame(width: defaultTileWidth, height: setSizeFromIndex())
.scaleEffect(
configuration.isPressed ? defaultTilesScaleFeedback : 1,
anchor: .center
)
.rotationEffect(
Angle(degrees: configuration.isPressed ? defaultTilesRotationFeedback : 0),
anchor: .center
)
.shadow(
color: .black.opacity(0.4),
radius: 3, x: 0, y: 3
)
}

private func setSizeFromIndex() -> CGFloat {
let sizeDiff = defaultTileHeightGap / tileNumber
let tileHeight = defaultMaxTileHeight - index * sizeDiff

return CGFloat(tileHeight)
}
}

}

#Preview {
Button {
// Nothing to do
} label: {
Color(.red)
}
.buttonStyle(MusicalInstrumentView.XylophoneView.TileButtonStyle(index: 0, tileNumber: 1))
}
Loading
Loading