diff --git a/assets/img/long_splash_after.png b/assets/img/long_splash_after.png new file mode 100644 index 0000000..f4e41f0 Binary files /dev/null and b/assets/img/long_splash_after.png differ diff --git a/assets/img/map_long.png b/assets/img/map_long.png new file mode 100644 index 0000000..928c22d Binary files /dev/null and b/assets/img/map_long.png differ diff --git a/octops.py b/octops.py index 16dd0f6..b262118 100644 --- a/octops.py +++ b/octops.py @@ -28,6 +28,7 @@ from screens.doors import DoorsScreen from screens.spawn import SpawnScreen from screens.map import MapScreen +from screens.long import LongScreen #--------------------------App--------------------------# @@ -45,6 +46,7 @@ def build(self): sm.add_widget(SiteAScreen(name='sitea')) sm.add_widget(DoorsScreen(name='doors')) sm.add_widget(SpawnScreen(name='spawn')) + sm.add_widget(LongScreen(name='long')) return sm diff --git a/screenLayout/long_screen.kv b/screenLayout/long_screen.kv new file mode 100644 index 0000000..fe5b9b8 --- /dev/null +++ b/screenLayout/long_screen.kv @@ -0,0 +1,234 @@ +: + FloatLayout: + # Initialize background splash image + BoxLayout: + id: splash_bg + opacity: 1 + AsyncImage: + source: 'assets/img/long_splash_after.png' + allow_stretch: True + keep_ratio: False + size_hint: 1, 1 + + # Initialize a matrix of 3x3 buttons each with unique id, text and position + Button: + id: 1 + text: "e" + font_size: "30sp" + color: 255,255,255 + halign: 'center' + valign: 'bottom' + background_color: 255,255,255 + size_hint: None,None + size: dp(30), dp(30) + pos: dp(100), dp(300) + disabled: True if splash_bg_after.opacity == 1 else False # Ensure buttons stay enabled until puzzle is solved + on_press: + root.change_img(self, 1) # Call function to toggle button image from grey to green upon press + root.check_product(self, 1) # Call function to check whether correct combination entered or not + + Image: + id: 1 + source: 'assets/img/symbols/off.png' # Initialize each button with a grey (off) image + center_x: self.parent.center_x + center_y: self.parent.top - 10 + + Button: + id: 2 + text: "e" + font_size: "30sp" + color: 255,255,255 + halign: 'center' + valign: 'bottom' + background_color: 255,255,255 + size_hint: None,None + size: dp(30), dp(30) + pos: dp(521), dp(467) + disabled: True if splash_bg_after.opacity == 1 else False + on_press: + root.change_img(self, 2) + root.check_product(self, 2) + + Image: + id: 2 + source: 'assets/img/symbols/off.png' + center_x: self.parent.center_x + center_y: self.parent.top - 10 + + Button: + id: 3 + text: "a" + font_size: "30sp" + color: 255,255,255 + halign: 'center' + valign: 'bottom' + background_color: 255,255,255 + size_hint: None,None + size: dp(30), dp(30) + pos: dp(475), dp(347) + disabled: True if splash_bg_after.opacity == 1 else False + on_press: + root.change_img(self, 3) + root.check_product(self, 3) + + Image: + id: 3 + source: 'assets/img/symbols/off.png' + center_x: self.parent.center_x + center_y: self.parent.top - 10 + + Button: + id: 4 + text: "a" + font_size: "30sp" + color: 255,255,255 + halign: 'center' + valign: 'bottom' + background_color: 255,255,255 + size_hint: None,None + size: dp(30), dp(30) + pos: dp(148), dp(372) + disabled: True if splash_bg_after.opacity == 1 else False + on_press: + root.change_img(self, 4) + root.check_product(self, 4) + + Image: + id: 4 + source: 'assets/img/symbols/off.png' + center_x: self.parent.center_x + center_y: self.parent.top - 10 + + Button: + id: 5 + text: "e" + font_size: "30sp" + color: 255,255,255 + halign: 'center' + valign: 'bottom' + background_color: 255,255,255 + size_hint: None,None + size: dp(30), dp(30) + pos: dp(261), dp(102) + disabled: True if splash_bg_after.opacity == 1 else False + on_press: + root.change_img(self, 5) + root.check_product(self, 5) + + Image: + id: 5 + source: 'assets/img/symbols/off.png' + center_x: self.parent.center_x + center_y: self.parent.top - 10 + + Button: + id: 6 + text: "a" + font_size: "30sp" + color: 255,255,255 + halign: 'center' + valign: 'bottom' + background_color: 255,255,255 + size_hint: None,None + size: dp(30), dp(30) + pos: dp(525), dp(242) + disabled: True if splash_bg_after.opacity == 1 else False + on_press: + root.change_img(self, 6) + root.check_product(self, 6) + + Image: + id: 6 + source: 'assets/img/symbols/off.png' + center_x: self.parent.center_x + center_y: self.parent.top - 10 + + Button: + id: 7 + text: "e" + font_size: "30sp" + color: 255,255,255 + halign: 'center' + valign: 'bottom' + background_color: 255,255,255 + size_hint: None,None + size: dp(30), dp(30) + pos: dp(148), dp(37) + disabled: True if splash_bg_after.opacity == 1 else False + on_press: + root.change_img(self, 7) + root.check_product(self, 7) + + Image: + id: 7 + source: 'assets/img/symbols/off.png' + center_x: self.parent.center_x + center_y: self.parent.top - 10 + + Button: + id: 8 + text: "a" + font_size: "30sp" + color: 255,255,255 + halign: 'center' + valign: 'bottom' + background_color: 255,255,255 + size_hint: None,None + size: dp(30), dp(30) + pos: dp(261), dp(337) + disabled: True if splash_bg_after.opacity == 1 else False + on_press: + root.change_img(self, 8) + root.check_product(self, 8) + + Image: + id: 8 + source: 'assets/img/symbols/off.png' + center_x: self.parent.center_x + center_y: self.parent.top - 10 + + Button: + id: 9 + text: "a" + font_size: "30sp" + color: 255,255,255 + halign: 'center' + valign: 'bottom' + background_color: 255,255,255 + size_hint: None,None + size: dp(30), dp(30) + pos: dp(375), dp(237) + disabled: True if splash_bg_after.opacity == 1 else False + on_press: + root.change_img(self, 9) + root.check_product(self, 9) + + Image: + id: 9 + source: 'assets/img/symbols/off.png' + center_x: self.parent.center_x + center_y: self.parent.top - 10 + + # Initialize background image to be switched to on correct combination + BoxLayout: + id: splash_bg_after + orientation: 'vertical' + opacity: 0 + AsyncImage: + source: 'assets/img/long_splash_after.png' + allow_stretch: True + keep_ratio: False + size_hint: 1, 1 + + # Initialize return button to map window + Button: + size_hint: None,None + size: dp(60), dp(60) + pos: dp(12), dp(523) + background_color: 0,0,0,0 + on_press: root.manager.current = 'map' + + Image: + source: 'assets/img/button_return.png' + center_x: self.parent.center_x + center_y: self.parent.center_y diff --git a/screenLayout/map_screen.kv b/screenLayout/map_screen.kv index 0f78f08..7114ff6 100644 --- a/screenLayout/map_screen.kv +++ b/screenLayout/map_screen.kv @@ -48,6 +48,21 @@ center_x: self.parent.center_x center_y: self.parent.center_y + #long + Button: + size_hint: None,None + size: dp(135), dp(135) + pos: dp(430), dp(225) + background_color: 0,0,0,0 + on_press: root.manager.current = 'long' + + Image: + source: 'assets/img/map_long.png' + size_hint: (1, 1) + size: dp(120), dp(120) + center_x: self.parent.center_x + center_y: self.parent.center_y + #doors Button: size_hint: None,None diff --git a/screenLayout/sitea_screen.kv b/screenLayout/sitea_screen.kv index 188812c..764eb58 100644 --- a/screenLayout/sitea_screen.kv +++ b/screenLayout/sitea_screen.kv @@ -44,10 +44,10 @@ size_hint: None,None size: dp(80), dp(80) pos: dp(261), dp(347) - disabled: True - - - + disabled: True if splash_bg_after.opacity == 1 else False + on_press: + root.change_img(self, 2) # Call function to toggle button image from grey to green upon press + root.check_product(self, 2) # Call function to check whether correct combination entered or not Image: id: 2 @@ -112,8 +112,8 @@ pos: dp(261), dp(242) disabled: True if splash_bg_after.opacity == 1 else False on_press: - root.change_img(self, 4) - root.check_product(self, 4) + root.change_img(self, 5) + root.check_product(self, 5) Image: id: 5 diff --git a/screens/doors.py b/screens/doors.py index f75985c..d39a898 100644 --- a/screens/doors.py +++ b/screens/doors.py @@ -9,25 +9,31 @@ class DoorsScreen(Screen): verified = False + # This method checks if the current value of the label is 9, if it is, then it sets the value of the label to 0. def increment_value(self, label_index): - if(int(label_index.text) == 5): + if(int(label_index.text) == 9): label_index.text = "0" else: label_index.text = f"{int(label_index.text) + 1}" + # After every decrement, checks if the resulting passcode is correct or not. DoorsScreen.verify(self) + # This method checks if the current value of the label is 0, if it is, then it sets the value of the label to 9. def decrement_value(self, label_index): if(int(label_index.text) == 0): label_index.text = "5" else: label_index.text = f"{int(label_index.text) - 1}" + # After every decrement, checks if the resulting passcode is correct or not. DoorsScreen.verify(self) + # First checks if the passcode entered is correct. Its calculated by concatenating the text values of four label objects. def verify(self): code = passcode == int(self.ids.label_1.text + self.ids.label_2.text + self.ids.label_3.text + self.ids.label_4.text) + # If the passcode is correct, then DoorsScreen.verify is set True. if not DoorsScreen.verified and code: DoorsScreen.verified = True - self.ids.splash_bg.opacity = 0 - self.ids.splash_bg_after.opacity = 1 - set_doors() - sound.play() \ No newline at end of file + self.ids.splash_bg.opacity = 0 # background splash image is faded out + self.ids.splash_bg_after.opacity = 1 # background splash image after is faded in. + set_doors() # set_doors() is called indicating the level is cleared. + sound.play() # sound is played. \ No newline at end of file diff --git a/screens/long.py b/screens/long.py new file mode 100644 index 0000000..abdbf82 --- /dev/null +++ b/screens/long.py @@ -0,0 +1,44 @@ +from kivy.lang import Builder +from kivy.uix.screenmanager import Screen +from kivy.core.audio import SoundLoader + +from .screen_check import set_long + +# Import and load .kv file containing widget and layout info along with audio files to be played in the window +Builder.load_file('screenLayout/long_screen.kv') +sound = SoundLoader.load('assets/audio/sitea_planted.wav') +class LongScreen(Screen): + pressed_buttons = [] + + def show_overlay(self): # Updating the window state after correct combination + self.ids.splash_bg.opacity = 0 + self.ids.splash_bg_after.opacity = 1 + self.pressed_buttons = [] + + def change_img(self, button, idOG): # Toggle the button states to on(green)/off(grey) on press + idOG_dynamic = f"{idOG}" + widget = getattr(self.ids, idOG_dynamic, None) + widget.source = "assets/img/symbols/on.png" if widget.source == "assets/img/symbols/off.png" else "assets/img/symbols/on.png" + + def check_product(self, instance, id): # Check for correct code combination + button_id = id + self.pressed_buttons.append(id) + x = "" + if len(self.pressed_buttons) == 4: # Check every 4 button press + product = 1 + for button_id in self.pressed_buttons: + product *= button_id + + if product == 70: # Check whether correct combination is entered + x = "Valid" + sound.play() + self.show_overlay() + set_long() # Update global long flag variable + else: + x = "Invalid" + + if x == "Invalid": # Toggle all on(green) button states to off(grey) and clear all previous entries + for button in self.pressed_buttons: + widget = getattr(self.ids, f"{button}", None) + widget.source = "assets/img/symbols/off.png" + self.pressed_buttons = [] diff --git a/screens/screen_check.py b/screens/screen_check.py index a449f24..2abf083 100644 --- a/screens/screen_check.py +++ b/screens/screen_check.py @@ -1,6 +1,7 @@ devMode = False sitea = devMode +long = devMode doors = devMode spawn = devMode passcode = 1275 #linked to bomb hints png @@ -14,6 +15,13 @@ def set_sitea(): def get_sitea(): return sitea +def set_long(): + global long + long = not long + +def get_long(): + return long + def set_doors(): global doors doors = not doors diff --git a/screens/siteA.py b/screens/siteA.py index b310bca..30e2254 100644 --- a/screens/siteA.py +++ b/screens/siteA.py @@ -18,7 +18,7 @@ def show_overlay(self): # Updating the window state after correct combination def change_img(self, button, idOG): # Toggle the button states to on(green)/off(grey) on press idOG_dynamic = f"{idOG}" widget = getattr(self.ids, idOG_dynamic, None) - widget.source = "assets/img/symbols/off.png" if widget.source == "assets/img/symbols/off.png" else "assets/img/symbols/off.png" + widget.source = "assets/img/symbols/on.png" if widget.source == "assets/img/symbols/off.png" else "assets/img/symbols/on.png" def check_product(self, instance, id): # Check for correct code combination button_id = id diff --git a/screens/siteB.py b/screens/siteB.py index 3704ba4..c687fbc 100644 --- a/screens/siteB.py +++ b/screens/siteB.py @@ -5,7 +5,7 @@ from kivy.uix.screenmanager import Screen from kivy.core.audio import SoundLoader -from .screen_check import passcode, get_spawn, get_doors, get_sitea, get_time +from .screen_check import passcode, get_spawn, get_doors, get_sitea, get_long, get_time from .map import MapScreen Builder.load_file('screenLayout/siteb_screen.kv') @@ -20,18 +20,18 @@ def Delay(delay): return Animation(duration=delay) def on_enter(self): - if not SiteBScreen.visited and not (get_spawn() and get_sitea() and get_doors()): + if not SiteBScreen.visited and not (get_spawn() and get_sitea() and get_doors() and get_long()): SiteBScreen.visited = True octocat_icon = self.Delay(0.5) + Animation(color=(1,1,1,1), pos= (dp(0), dp(0)), duration=0.2, t='out_quad') + self.Delay(3.5) + Animation(color=(1,1,1,0), duration=0.2, t='out_quad') octocat_icon.start(self.ids.octocat_icon) text_bubble = self.Delay(1) + Animation(color=(1,1,1,1), pos = (dp(233), dp(155)), duration=0.2, t='out_quad') + self.Delay(3.5) + Animation(color=(1,1,1,0), pos = (dp(233), dp(155)), duration=0.2, t='out_quad') text_bubble.start(self.ids.octocat_hint) - if get_spawn() and get_sitea() and get_doors() and not SiteBScreen.defused: + if get_spawn() and get_sitea() and get_doors() and get_long() and not SiteBScreen.defused: self.ids.defuse_img.color = (1,1,1,1) def defuse_btn_press(self): - if get_sitea() and get_doors() and get_spawn() and not SiteBScreen.defused: + if get_sitea() and get_doors() and get_spawn() and get_long() and not SiteBScreen.defused: SiteBScreen.defused = True MapScreen.stop_timer(self) Animation(color= (1,1,1,0.5), duration=0.5).start(self.ids.defuse_img) diff --git a/screens/spawn.py b/screens/spawn.py index f770ff0..5762717 100644 --- a/screens/spawn.py +++ b/screens/spawn.py @@ -10,7 +10,7 @@ class SpawnScreen(Screen): verified = False def slider_val_change(self): - if not SpawnScreen.verified and ((self.ids.slide1.value < slider[0]+5) and (self.ids.slide1.value > slider[0]-5 )) and ((self.ids.slide2.value < slider[2]+5)and ( self.ids.slide2.value > slider[2]-5 )) and ((self.ids.slide3.value < slider[2]+5) and (self.ids.slide3.value > slider[2]-5 )): + if not SpawnScreen.verified and ((self.ids.slide1.value < slider[0]+5) and (self.ids.slide1.value > slider[0]-5 )) and ((self.ids.slide2.value < slider[1]+5)and ( self.ids.slide2.value > slider[1]-5 )) and ((self.ids.slide3.value < slider[2]+5) and (self.ids.slide3.value > slider[2]-5 )): SpawnScreen.verified = True self.ids.splash_bg.opacity = 0 self.ids.splash_bg_after.opacity = 1