Vittesh Raghavan Logo Vittesh Raghavan
Conquering of The Royal Keep Thumbnail

Conquering of The Royal Keep

Black Banshee Studios
Tools used Team Size My Role
Ren'Py Unreal Engine Photoshop Github
9
Lead Programmer

Summary

Conquering of the Royal Keep is a decision driven, visual novel game in which the player takes on the persona of a squire of the Royal Guard, entering their final stage of training to become a full knight. However, there is more to the Royal Keep that meets the eye. As the squire makes their way through the trials and tribulations set forth by their last task, it is soon noticed that something about this keep is wrong, and the squire must face their death time and time again until they can finally conquer the mysteries of the Royal Keep.

Contributions & Responsibilities

  • Scripted gameplay and dialogue systems in Python using Ren’Py engine.
  • Designed and Scripted navigation and puzzle mechanics.
  • Designed and Implemented interactive image buttons using Photoshop.
  • Conducted comprehensive QA testing, debugging, and performance optimization to deliver a polished final build.
  • Trailer

    Dialouge and QTE mechanics

    Code
    1. init offset = -5
    2. default rotate_speed = 1.4
    3. default chest_unlocked = False
    4. default current_rotation = 0
    5. default chest_unlock_tries = 3
    6. default randomno = renpy.random.randint(1,360)
    7. init python:
    8. def update_rotation(trans, st, at):
    9. current_rotation = (st * 360 / rotate_speed)%360
    10. trans.rotate = current_rotation
    11. return 0
    12. def safezone_check(current, target, lowerlimit, upperlimit):
    13. diff = (current - target + 180) % 360 - 180
    14. return -lowerlimit < diff < upperlimit
    15. def check_slider():
    16. if safezone_check(current_rotation,randomno,20,25):
    17. renpy.store.chest_unlocked = True
    18. renpy.play("sound_effects/sfx_Puzzle2_Success.mp3", channel="sound")
    19. renpy.jump("CtRK_lavatrapRoom_camera2")
    20. else:
    21. renpy.store.chest_unlock_tries -= 1
    22. def reset_puzzle():
    23. renpy.store.randomno = renpy.random.randint(1,360)
    24. renpy.store.rotate_speed = 2
    25. renpy.store.chest_unlock_tries = 3
    26. renpy.store.chest_unlocked = False
    27. screen solve_puzzle():
    28. modal True
    29. if chest_unlocked:
    30. timer 0.1 action [Hide("solve_puzzle"),Function(reset_puzzle)]
    31. elif not chest_unlocked and chest_unlock_tries>0:
    32. frame:
    33. background "#FFFFFF"
    34. add safe_zone_image at rotate_random
    35. add slider_image at rotating
    36. key "mousedown_1" action [Function(check_slider)]

    Refactoring Code

    This section talks about how I refactred the code to have a more modular and flexible structure

    Old Code
    1. screen CtRK_sawtrapRoom_camera1_nav():
    2. modal True
    3. imagebutton auto "bg_general_moveback_%s":
    4. focus_mask True
    5. hover_sound "sound_effects/sfx_SingleTapStone2.mp3"
    6. action [Jump ("CtRK_torchRoom_camera5")]
    7. imagebutton auto "bg_sawtraproom_camera1_camera2wall_%s":
    8. focus_mask True
    9. hover_sound "sound_effects/sfx_SingleTapStone2.mp3"
    10. hovered [Notify ("Lever1")]
    11. action [Jump ("CtRK_sawtrapRoom_camera2")]
    12. imagebutton auto "bg_sawtraproom_camera1_hallway1_%s":
    13. focus_mask True
    14. hover_sound "sound_effects/sfx_SingleTapStone2.mp3"
    15. hovered [Notify ("Camera 8")]
    16. action [Jump ("CtRK_sawtrapRoom_camera8")]
    17. imagebutton auto "bg_sawtraproom_camera1_hallway2_%s":
    18. focus_mask True
    19. hover_sound "sound_effects/sfx_SingleTapStone2.mp3"
    20. hovered [Notify ("Camera 7")]
    21. action [Jump ("CtRK_sawtrapRoom_camera7")]
    22. imagebutton auto "bg_sawtraproom_camera1_hallway3_%s":
    23. focus_mask True
    24. hover_sound "sound_effects/sfx_SingleTapStone2.mp3"
    25. hovered [Notify ("Hallway 1")]
    26. action [Jump ("camera3_hallway")]
    27. imagebutton auto "bg_sawtraproom_camera1_hallway4_%s":
    28. focus_mask True
    29. hover_sound "sound_effects/sfx_SingleTapStone2.mp3"
    30. hovered [Notify ("Hallway 2")]
    31. action [Jump ("CtRK_sawtrapRoom_camera4")]
    32. if lever2_activated:
    33. imagebutton auto "bg_sawtraproom_camera1_hallway5_trapdeactivated_%s":
    34. focus_mask True
    35. hover_sound "sound_effects/sfx_SingleTapStone2.mp3"
    36. hovered [Notify ("Hallway 3")]
    37. action [Jump ("CtRK_sawtrapRoom_camera5")]
    38. else:
    39. imagebutton auto "bg_sawtraproom_camera1_hallway5_trapactive_%s":
    40. focus_mask True
    41. hover_sound "sound_effects/sfx_SingleTapStone2.mp3"
    42. hovered [Notify ("Hallway 3")]
    43. action [Jump ("CtRK_sawtrapRoom_camera5")]
    44. if lever3_activated and lever5_activated:
    45. imagebutton auto "bg_sawtraproom_camera1_hallway6_trapdeactivated_leverdown_%s":
    46. focus_mask True
    47. hover_sound "sound_effects/sfx_SingleTapStone2.mp3"
    48. hovered [Notify ("Hallway 4")]
    49. action [Jump ("CtRK_sawtrapRoom_camera6")]
    50. elif lever3_activated and lever5_activated == False:
    51. imagebutton auto "bg_sawtraproom_camera1_hallway6_trapdeactivated_leverup_%s":
    52. focus_mask True
    53. hover_sound "sound_effects/sfx_SingleTapStone2.mp3"
    54. hovered [Notify ("Hallway 4")]
    55. action [Jump ("CtRK_sawtrapRoom_camera6")]
    56. else:
    57. imagebutton auto "bg_sawtraproom_camera1_hallway6_%s":
    58. focus_mask True
    59. hover_sound "sound_effects/sfx_SingleTapStone2.mp3"
    60. hovered [Notify ("Hallway 4")]
    61. action [Notify ("That way is blocked...")]
    Refactored Code
    1. ################################################# List of Actions
    2. default spyroom_camera1_moveback_actions = [Jump("CtRK_spyRoom_camera2")]
    3. default spyroom_camera1_bookshelf_actions = [Jump("spyRoom_camera1_bookshelf_script")]
    4. default spyroom_camera1_chest_actions = [Jump("spyRoom_camera1_chest_script")]
    5. default spyroom_camera1_rug_actions = [Jump("spyRoom_camera1_rug_script")]
    6. default spyroom_camera1_box_actions = [Jump("spyRoom_camera1_box_script")]
    7. default spyroom_camera2_moveback_actions = [Jump("CtRK_spyRoom_camera1")]
    8. default spyroom_camera2_door_actions = [Jump("CtRK_lavatrapRoom_camera6")]
    9. ################################################# List of Image buttons
    10. default spyroom_camera1_moveback = imageButtonRef("bg_general_moveback", True, "", spyroom_camera1_moveback_actions, True)
    11. default spyroom_camera1_bookshelf = imageButtonRef("bg_spyroom_camera1_bookshelf", True, "", spyroom_camera1_bookshelf_actions, True)
    12. default spyroom_camera1_chest = imageButtonRef("bg_spyroom_camera1_chest", True, "", spyroom_camera1_chest_actions, True)
    13. default spyroom_camera1_rug = imageButtonRef("bg_spyroom_camera1_rug", True, "", spyroom_camera1_rug_actions, True)
    14. default spyroom_camera1_box = imageButtonRef("bg_spyroom_camera1_box", True, "", spyroom_camera1_box_actions, True)
    15. default spyroom_camera2_moveback = imageButtonRef("bg_general_moveback", True, "", spyroom_camera2_moveback_actions, True)
    16. default spyroom_camera2_door = imageButtonRef("bg_spyroom_camera2_door", True, "", spyroom_camera2_door_actions, True)
    17. ################################################# List of Cameras
    18. default spyroom_camera1 = room([ spyroom_camera1_box,
    19. spyroom_camera1_rug,
    20. spyroom_camera1_chest,
    21. spyroom_camera1_bookshelf,
    22. spyroom_camera1_moveback])
    23. default spyroom_camera2 = room([ spyroom_camera2_door, spyroom_camera2_moveback])
    24. #################################################
    25. screen spyRoom_nav(RoomRef):
    26. modal True
    27. for imageButton in RoomRef.imageButtonRefs:
    28. if imageButton.isActive:
    29. imagebutton auto imageButton.image + "_%s":
    30. hover_sound "sound_effects/sfx_SingleTapStone2.mp3"
    31. focus_mask imageButton.focus_mask
    32. if imageButton.sound != "":
    33. activate_sound imageButton.sound
    34. action imageButton.actions

    -

    Research Summary

    When developing Conquering of the Royal Keep, my process was shaped by rapid prototyping guidelines from Taylor’s (2022) GDC talk, How to Create Rapid Prototypes, including shortening design loops and exposing critical problems early in the development stage (Black Banshee Studios, n.d.). I used these tactics when developing prototypes of time-based puzzles, levels, and various game mechanics (Black Banshee Studios, n.d.; Taylor, 2022). Following those guidelines streamlined my workflow for this project (Black Banshee Studios, n.d.; Taylor, 2022).

    References