summaryrefslogtreecommitdiffhomepage
path: root/samples/07_advanced_rendering/08_splitscreen_camera
diff options
context:
space:
mode:
Diffstat (limited to 'samples/07_advanced_rendering/08_splitscreen_camera')
-rw-r--r--samples/07_advanced_rendering/08_splitscreen_camera/app/main.rb396
-rw-r--r--samples/07_advanced_rendering/08_splitscreen_camera/replay.txt226
-rw-r--r--samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_down_standing.pngbin0 -> 186 bytes
-rw-r--r--samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_left_standing.pngbin0 -> 173 bytes
-rw-r--r--samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_right_standing.pngbin0 -> 170 bytes
-rw-r--r--samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_up_standing.pngbin0 -> 165 bytes
-rw-r--r--samples/07_advanced_rendering/08_splitscreen_camera/sprites/rooms/camera_room.pngbin0 -> 2469 bytes
7 files changed, 622 insertions, 0 deletions
diff --git a/samples/07_advanced_rendering/08_splitscreen_camera/app/main.rb b/samples/07_advanced_rendering/08_splitscreen_camera/app/main.rb
new file mode 100644
index 0000000..9d22918
--- /dev/null
+++ b/samples/07_advanced_rendering/08_splitscreen_camera/app/main.rb
@@ -0,0 +1,396 @@
+class CameraMovement
+ attr_accessor :state, :inputs, :outputs, :grid
+
+ #==============================================================================================
+ #Serialize
+ def serialize
+ {state: state, inputs: inputs, outputs: outputs, grid: grid }
+ end
+
+ def inspect
+ serialize.to_s
+ end
+
+ def to_s
+ serialize.to_s
+ end
+
+ #==============================================================================================
+ #Tick
+ def tick
+ defaults
+ calc
+ render
+ input
+ end
+
+ #==============================================================================================
+ #Default functions
+ def defaults
+ outputs[:scene].background_color = [0,0,0]
+ state.trauma ||= 0.0
+ state.trauma_power ||= 2
+ state.player_cyan ||= new_player_cyan
+ state.player_magenta ||= new_player_magenta
+ state.camera_magenta ||= new_camera_magenta
+ state.camera_cyan ||= new_camera_cyan
+ state.camera_center ||= new_camera_center
+ state.room ||= new_room
+ end
+
+ def default_player x, y, w, h, sprite_path
+ state.new_entity(:player,
+ { x: x,
+ y: y,
+ dy: 0,
+ dx: 0,
+ w: w,
+ h: h,
+ damage: 0,
+ dead: false,
+ orientation: "down",
+ max_alpha: 255,
+ sprite_path: sprite_path})
+ end
+
+ def default_floor_tile x, y, w, h, sprite_path
+ state.new_entity(:room,
+ { x: x,
+ y: y,
+ w: w,
+ h: h,
+ sprite_path: sprite_path})
+ end
+
+ def default_camera x, y, w, h
+ state.new_entity(:camera,
+ { x: x,
+ y: y,
+ dx: 0,
+ dy: 0,
+ w: w,
+ h: h})
+ end
+
+ def new_player_cyan
+ default_player(0, 0, 64, 64,
+ "sprites/player/player_#{state.player_cyan.orientation}_standing.png")
+ end
+
+ def new_player_magenta
+ default_player(64, 0, 64, 64,
+ "sprites/player/player_#{state.player_magenta.orientation}_standing.png")
+ end
+
+ def new_camera_magenta
+ default_camera(0,0,720,720)
+ end
+
+ def new_camera_cyan
+ default_camera(0,0,720,720)
+ end
+
+ def new_camera_center
+ default_camera(0,0,1280,720)
+ end
+
+
+ def new_room
+ default_floor_tile(0,0,1024,1024,'sprites/rooms/camera_room.png')
+ end
+
+ #==============================================================================================
+ #Calculation functions
+ def calc
+ calc_camera_magenta
+ calc_camera_cyan
+ calc_camera_center
+ calc_player_cyan
+ calc_player_magenta
+ calc_trauma_decay
+ end
+
+ def center_camera_tolerance
+ return Math.sqrt(((state.player_magenta.x - state.player_cyan.x) ** 2) +
+ ((state.player_magenta.y - state.player_cyan.y) ** 2)) > 640
+ end
+
+ def calc_player_cyan
+ state.player_cyan.x += state.player_cyan.dx
+ state.player_cyan.y += state.player_cyan.dy
+ end
+
+ def calc_player_magenta
+ state.player_magenta.x += state.player_magenta.dx
+ state.player_magenta.y += state.player_magenta.dy
+ end
+
+ def calc_camera_center
+ timeScale = 1
+ midX = (state.player_magenta.x + state.player_cyan.x)/2
+ midY = (state.player_magenta.y + state.player_cyan.y)/2
+ targetX = midX - state.camera_center.w/2
+ targetY = midY - state.camera_center.h/2
+ state.camera_center.x += (targetX - state.camera_center.x) * 0.1 * timeScale
+ state.camera_center.y += (targetY - state.camera_center.y) * 0.1 * timeScale
+ end
+
+
+ def calc_camera_magenta
+ timeScale = 1
+ targetX = state.player_magenta.x + state.player_magenta.w - state.camera_magenta.w/2
+ targetY = state.player_magenta.y + state.player_magenta.h - state.camera_magenta.h/2
+ state.camera_magenta.x += (targetX - state.camera_magenta.x) * 0.1 * timeScale
+ state.camera_magenta.y += (targetY - state.camera_magenta.y) * 0.1 * timeScale
+ end
+
+ def calc_camera_cyan
+ timeScale = 1
+ targetX = state.player_cyan.x + state.player_cyan.w - state.camera_cyan.w/2
+ targetY = state.player_cyan.y + state.player_cyan.h - state.camera_cyan.h/2
+ state.camera_cyan.x += (targetX - state.camera_cyan.x) * 0.1 * timeScale
+ state.camera_cyan.y += (targetY - state.camera_cyan.y) * 0.1 * timeScale
+ end
+
+ def calc_player_quadrant angle
+ if angle < 45 and angle > -45 and state.player_cyan.x < state.player_magenta.x
+ return 1
+ elsif angle < 45 and angle > -45 and state.player_cyan.x > state.player_magenta.x
+ return 3
+ elsif (angle > 45 or angle < -45) and state.player_cyan.y < state.player_magenta.y
+ return 2
+ elsif (angle > 45 or angle < -45) and state.player_cyan.y > state.player_magenta.y
+ return 4
+ end
+ end
+
+ def calc_camera_shake
+ state.trauma
+ end
+
+ def calc_trauma_decay
+ state.trauma = state.trauma * 0.9
+ end
+
+ def calc_random_float_range(min, max)
+ rand * (max-min) + min
+ end
+
+ #==============================================================================================
+ #Render Functions
+ def render
+ render_floor
+ render_player_cyan
+ render_player_magenta
+ if center_camera_tolerance
+ render_split_camera_scene
+ else
+ render_camera_center_scene
+ end
+ end
+
+ def render_player_cyan
+ outputs[:scene].sprites << {x: state.player_cyan.x,
+ y: state.player_cyan.y,
+ w: state.player_cyan.w,
+ h: state.player_cyan.h,
+ path: "sprites/player/player_#{state.player_cyan.orientation}_standing.png",
+ r: 0,
+ g: 255,
+ b: 255}
+ end
+
+ def render_player_magenta
+ outputs[:scene].sprites << {x: state.player_magenta.x,
+ y: state.player_magenta.y,
+ w: state.player_magenta.w,
+ h: state.player_magenta.h,
+ path: "sprites/player/player_#{state.player_magenta.orientation}_standing.png",
+ r: 255,
+ g: 0,
+ b: 255}
+ end
+
+ def render_floor
+ outputs[:scene].sprites << [state.room.x, state.room.y,
+ state.room.w, state.room.h,
+ state.room.sprite_path]
+ end
+
+ def render_camera_center_scene
+ zoomFactor = 1
+ outputs[:scene].width = state.room.w
+ outputs[:scene].height = state.room.h
+
+ maxAngle = 10.0
+ maxOffset = 20.0
+ angle = maxAngle * calc_camera_shake * calc_random_float_range(-1,1)
+ offsetX = 32 - (maxOffset * calc_camera_shake * calc_random_float_range(-1,1))
+ offsetY = 32 - (maxOffset * calc_camera_shake * calc_random_float_range(-1,1))
+
+ outputs.sprites << {x: (-state.camera_center.x - offsetX)/zoomFactor,
+ y: (-state.camera_center.y - offsetY)/zoomFactor,
+ w: outputs[:scene].width/zoomFactor,
+ h: outputs[:scene].height/zoomFactor,
+ path: :scene,
+ angle: angle,
+ source_w: -1,
+ source_h: -1}
+ outputs.labels << [128,64,"#{state.trauma.round(1)}",8,2,255,0,255,255]
+ end
+
+ def render_split_camera_scene
+ outputs[:scene].width = state.room.w
+ outputs[:scene].height = state.room.h
+ render_camera_magenta_scene
+ render_camera_cyan_scene
+
+ angle = Math.atan((state.player_magenta.y - state.player_cyan.y)/(state.player_magenta.x- state.player_cyan.x)) * 180/Math::PI
+ output_split_camera angle
+
+ end
+
+ def render_camera_magenta_scene
+ zoomFactor = 1
+ offsetX = 32
+ offsetY = 32
+
+ outputs[:scene_magenta].sprites << {x: (-state.camera_magenta.x*2),
+ y: (-state.camera_magenta.y),
+ w: outputs[:scene].width*2,
+ h: outputs[:scene].height,
+ path: :scene}
+
+ end
+
+ def render_camera_cyan_scene
+ zoomFactor = 1
+ offsetX = 32
+ offsetY = 32
+ outputs[:scene_cyan].sprites << {x: (-state.camera_cyan.x*2),
+ y: (-state.camera_cyan.y),
+ w: outputs[:scene].width*2,
+ h: outputs[:scene].height,
+ path: :scene}
+ end
+
+ def output_split_camera angle
+ #TODO: Clean this up!
+ quadrant = calc_player_quadrant angle
+ outputs.labels << [128,64,"#{quadrant}",8,2,255,0,255,255]
+ if quadrant == 1
+ set_camera_attributes(w: 640, h: 720, m_x: 640, m_y: 0, c_x: 0, c_y: 0)
+
+ elsif quadrant == 2
+ set_camera_attributes(w: 1280, h: 360, m_x: 0, m_y: 360, c_x: 0, c_y: 0)
+
+ elsif quadrant == 3
+ set_camera_attributes(w: 640, h: 720, m_x: 0, m_y: 0, c_x: 640, c_y: 0)
+
+ elsif quadrant == 4
+ set_camera_attributes(w: 1280, h: 360, m_x: 0, m_y: 0, c_x: 0, c_y: 360)
+
+ end
+ end
+
+ def set_camera_attributes(w: 0, h: 0, m_x: 0, m_y: 0, c_x: 0, c_y: 0)
+ state.camera_cyan.w = w + 64
+ state.camera_cyan.h = h + 64
+ outputs[:scene_cyan].width = (w) * 2
+ outputs[:scene_cyan].height = h
+
+ state.camera_magenta.w = w + 64
+ state.camera_magenta.h = h + 64
+ outputs[:scene_magenta].width = (w) * 2
+ outputs[:scene_magenta].height = h
+ outputs.sprites << {x: m_x,
+ y: m_y,
+ w: w,
+ h: h,
+ path: :scene_magenta}
+ outputs.sprites << {x: c_x,
+ y: c_y,
+ w: w,
+ h: h,
+ path: :scene_cyan}
+ end
+
+ def add_trauma amount
+ state.trauma = [state.trauma + amount, 1.0].min
+ end
+
+ def remove_trauma amount
+ state.trauma = [state.trauma - amount, 0.0].max
+ end
+ #==============================================================================================
+ #Input functions
+ def input
+ input_move_cyan
+ input_move_magenta
+
+ if inputs.keyboard.key_down.t
+ add_trauma(0.5)
+ elsif inputs.keyboard.key_down.y
+ remove_trauma(0.1)
+ end
+ end
+
+ def input_move_cyan
+ if inputs.keyboard.key_held.up
+ state.player_cyan.dy = 5
+ state.player_cyan.orientation = "up"
+ elsif inputs.keyboard.key_held.down
+ state.player_cyan.dy = -5
+ state.player_cyan.orientation = "down"
+ else
+ state.player_cyan.dy *= 0.8
+ end
+ if inputs.keyboard.key_held.left
+ state.player_cyan.dx = -5
+ state.player_cyan.orientation = "left"
+ elsif inputs.keyboard.key_held.right
+ state.player_cyan.dx = 5
+ state.player_cyan.orientation = "right"
+ else
+ state.player_cyan.dx *= 0.8
+ end
+
+ outputs.labels << [128,512,"#{state.player_cyan.x.round()}",8,2,0,255,255,255]
+ outputs.labels << [128,480,"#{state.player_cyan.y.round()}",8,2,0,255,255,255]
+ end
+
+ def input_move_magenta
+ if inputs.keyboard.key_held.w
+ state.player_magenta.dy = 5
+ state.player_magenta.orientation = "up"
+ elsif inputs.keyboard.key_held.s
+ state.player_magenta.dy = -5
+ state.player_magenta.orientation = "down"
+ else
+ state.player_magenta.dy *= 0.8
+ end
+ if inputs.keyboard.key_held.a
+ state.player_magenta.dx = -5
+ state.player_magenta.orientation = "left"
+ elsif inputs.keyboard.key_held.d
+ state.player_magenta.dx = 5
+ state.player_magenta.orientation = "right"
+ else
+ state.player_magenta.dx *= 0.8
+ end
+
+ outputs.labels << [128,360,"#{state.player_magenta.x.round()}",8,2,255,0,255,255]
+ outputs.labels << [128,328,"#{state.player_magenta.y.round()}",8,2,255,0,255,255]
+ end
+end
+
+$camera_movement = CameraMovement.new
+
+def tick args
+ args.outputs.background_color = [0,0,0]
+ $camera_movement.inputs = args.inputs
+ $camera_movement.outputs = args.outputs
+ $camera_movement.state = args.state
+ $camera_movement.grid = args.grid
+ $camera_movement.tick
+end
diff --git a/samples/07_advanced_rendering/08_splitscreen_camera/replay.txt b/samples/07_advanced_rendering/08_splitscreen_camera/replay.txt
new file mode 100644
index 0000000..b0c548e
--- /dev/null
+++ b/samples/07_advanced_rendering/08_splitscreen_camera/replay.txt
@@ -0,0 +1,226 @@
+replay_version 2.0
+stopped_at 1047
+seed 100
+recorded_at Sat Jul 17 09:23:22 2021
+[:mouse_button_up, 1, 0, 1, 1, 5]
+[:mouse_move, 795, 98, 2, 2, 75]
+[:mouse_move, 797, 100, 2, 3, 77]
+[:mouse_move, 799, 101, 2, 4, 78]
+[:mouse_move, 800, 101, 2, 5, 78]
+[:mouse_button_pressed, 1, 0, 1, 6, 88]
+[:mouse_button_up, 1, 0, 1, 7, 92]
+[:key_down_raw, 1073741903, 0, 2, 8, 124]
+[:key_down_raw, 1073741903, 0, 2, 9, 138]
+[:key_down_raw, 1073741903, 0, 2, 10, 141]
+[:key_down_raw, 1073741903, 0, 2, 11, 142]
+[:key_down_raw, 1073741903, 0, 2, 12, 144]
+[:key_down_raw, 1073741903, 0, 2, 13, 147]
+[:key_down_raw, 1073741903, 0, 2, 14, 148]
+[:key_down_raw, 1073741903, 0, 2, 15, 151]
+[:key_down_raw, 1073741906, 0, 2, 16, 151]
+[:key_down_raw, 1073741906, 0, 2, 17, 166]
+[:key_down_raw, 1073741906, 0, 2, 18, 169]
+[:key_down_raw, 1073741906, 0, 2, 19, 170]
+[:key_down_raw, 1073741906, 0, 2, 20, 172]
+[:key_down_raw, 1073741906, 0, 2, 21, 174]
+[:key_down_raw, 1073741906, 0, 2, 22, 177]
+[:key_down_raw, 1073741906, 0, 2, 23, 178]
+[:key_down_raw, 1073741906, 0, 2, 24, 180]
+[:key_down_raw, 1073741906, 0, 2, 25, 182]
+[:key_down_raw, 1073741906, 0, 2, 26, 184]
+[:key_down_raw, 1073741906, 0, 2, 27, 186]
+[:key_down_raw, 1073741906, 0, 2, 28, 188]
+[:key_down_raw, 1073741906, 0, 2, 29, 190]
+[:key_down_raw, 1073741906, 0, 2, 30, 193]
+[:key_down_raw, 1073741906, 0, 2, 31, 194]
+[:key_up_raw, 1073741906, 0, 2, 32, 195]
+[:key_up_raw, 1073741903, 0, 2, 33, 291]
+[:key_down_raw, 119, 0, 2, 34, 360]
+[:key_down_raw, 119, 0, 2, 35, 375]
+[:key_down_raw, 119, 0, 2, 36, 378]
+[:key_down_raw, 119, 0, 2, 37, 379]
+[:key_down_raw, 119, 0, 2, 38, 381]
+[:key_down_raw, 119, 0, 2, 39, 383]
+[:key_down_raw, 119, 0, 2, 40, 385]
+[:key_down_raw, 119, 0, 2, 41, 387]
+[:key_down_raw, 119, 0, 2, 42, 389]
+[:key_down_raw, 119, 0, 2, 43, 391]
+[:key_down_raw, 119, 0, 2, 44, 393]
+[:key_down_raw, 119, 0, 2, 45, 395]
+[:key_down_raw, 119, 0, 2, 46, 397]
+[:key_down_raw, 119, 0, 2, 47, 401]
+[:key_down_raw, 119, 0, 2, 48, 403]
+[:key_down_raw, 119, 0, 2, 49, 405]
+[:key_down_raw, 119, 0, 2, 50, 407]
+[:key_down_raw, 119, 0, 2, 51, 409]
+[:key_down_raw, 119, 0, 2, 52, 411]
+[:key_down_raw, 119, 0, 2, 53, 412]
+[:key_down_raw, 119, 0, 2, 54, 414]
+[:key_down_raw, 119, 0, 2, 55, 416]
+[:key_down_raw, 119, 0, 2, 56, 419]
+[:key_down_raw, 119, 0, 2, 57, 421]
+[:key_down_raw, 119, 0, 2, 58, 422]
+[:key_down_raw, 119, 0, 2, 59, 424]
+[:key_down_raw, 119, 0, 2, 60, 426]
+[:key_down_raw, 119, 0, 2, 61, 429]
+[:key_down_raw, 119, 0, 2, 62, 431]
+[:key_down_raw, 119, 0, 2, 63, 432]
+[:key_down_raw, 119, 0, 2, 64, 434]
+[:key_down_raw, 119, 0, 2, 65, 436]
+[:key_down_raw, 119, 0, 2, 66, 438]
+[:key_down_raw, 119, 0, 2, 67, 441]
+[:key_down_raw, 119, 0, 2, 68, 443]
+[:key_down_raw, 119, 0, 2, 69, 444]
+[:key_down_raw, 119, 0, 2, 70, 446]
+[:key_down_raw, 119, 0, 2, 71, 449]
+[:key_down_raw, 119, 0, 2, 72, 451]
+[:key_down_raw, 119, 0, 2, 73, 453]
+[:key_down_raw, 119, 0, 2, 74, 455]
+[:key_down_raw, 119, 0, 2, 75, 457]
+[:key_down_raw, 119, 0, 2, 76, 459]
+[:key_down_raw, 119, 0, 2, 77, 460]
+[:key_down_raw, 119, 0, 2, 78, 462]
+[:key_down_raw, 119, 0, 2, 79, 464]
+[:key_down_raw, 119, 0, 2, 80, 467]
+[:key_down_raw, 119, 0, 2, 81, 468]
+[:key_down_raw, 119, 0, 2, 82, 471]
+[:key_down_raw, 119, 0, 2, 83, 473]
+[:key_down_raw, 119, 0, 2, 84, 474]
+[:key_down_raw, 119, 0, 2, 85, 476]
+[:key_down_raw, 119, 0, 2, 86, 478]
+[:key_down_raw, 119, 0, 2, 87, 481]
+[:key_down_raw, 119, 0, 2, 88, 482]
+[:key_down_raw, 119, 0, 2, 89, 484]
+[:key_down_raw, 119, 0, 2, 90, 486]
+[:key_down_raw, 119, 0, 2, 91, 489]
+[:key_down_raw, 119, 0, 2, 92, 491]
+[:key_down_raw, 119, 0, 2, 93, 493]
+[:key_down_raw, 119, 0, 2, 94, 494]
+[:key_down_raw, 119, 0, 2, 95, 496]
+[:key_down_raw, 119, 0, 2, 96, 498]
+[:key_down_raw, 119, 0, 2, 97, 501]
+[:key_down_raw, 119, 0, 2, 98, 502]
+[:key_down_raw, 119, 0, 2, 99, 505]
+[:key_down_raw, 119, 0, 2, 100, 507]
+[:key_down_raw, 119, 0, 2, 101, 509]
+[:key_down_raw, 119, 0, 2, 102, 511]
+[:key_down_raw, 119, 0, 2, 103, 512]
+[:key_down_raw, 119, 0, 2, 104, 514]
+[:key_down_raw, 119, 0, 2, 105, 516]
+[:key_down_raw, 119, 0, 2, 106, 519]
+[:key_down_raw, 119, 0, 2, 107, 521]
+[:key_down_raw, 119, 0, 2, 108, 523]
+[:key_down_raw, 119, 0, 2, 109, 524]
+[:key_down_raw, 119, 0, 2, 110, 526]
+[:key_down_raw, 119, 0, 2, 111, 529]
+[:key_down_raw, 119, 0, 2, 112, 530]
+[:key_down_raw, 119, 0, 2, 113, 533]
+[:key_down_raw, 119, 0, 2, 114, 535]
+[:key_down_raw, 119, 0, 2, 115, 536]
+[:key_up_raw, 119, 0, 2, 116, 536]
+[:key_down_raw, 100, 0, 2, 117, 548]
+[:key_down_raw, 100, 0, 2, 118, 563]
+[:key_down_raw, 100, 0, 2, 119, 565]
+[:key_down_raw, 100, 0, 2, 120, 567]
+[:key_down_raw, 100, 0, 2, 121, 569]
+[:key_down_raw, 100, 0, 2, 122, 572]
+[:key_down_raw, 100, 0, 2, 123, 573]
+[:key_down_raw, 100, 0, 2, 124, 576]
+[:key_down_raw, 100, 0, 2, 125, 577]
+[:key_down_raw, 100, 0, 2, 126, 579]
+[:key_down_raw, 100, 0, 2, 127, 582]
+[:key_down_raw, 100, 0, 2, 128, 584]
+[:key_down_raw, 100, 0, 2, 129, 585]
+[:key_down_raw, 100, 0, 2, 130, 588]
+[:key_down_raw, 100, 0, 2, 131, 589]
+[:key_down_raw, 100, 0, 2, 132, 591]
+[:key_down_raw, 100, 0, 2, 133, 593]
+[:key_down_raw, 100, 0, 2, 134, 595]
+[:key_down_raw, 100, 0, 2, 135, 597]
+[:key_down_raw, 100, 0, 2, 136, 599]
+[:key_down_raw, 100, 0, 2, 137, 601]
+[:key_down_raw, 100, 0, 2, 138, 603]
+[:key_down_raw, 100, 0, 2, 139, 605]
+[:key_down_raw, 100, 0, 2, 140, 607]
+[:key_up_raw, 100, 0, 2, 141, 608]
+[:key_down_raw, 100, 0, 2, 142, 646]
+[:key_up_raw, 100, 0, 2, 143, 654]
+[:key_down_raw, 1073741906, 0, 2, 144, 696]
+[:key_down_raw, 1073741906, 0, 2, 145, 711]
+[:key_down_raw, 1073741906, 0, 2, 146, 713]
+[:key_down_raw, 1073741906, 0, 2, 147, 715]
+[:key_down_raw, 1073741906, 0, 2, 148, 717]
+[:key_down_raw, 1073741906, 0, 2, 149, 719]
+[:key_down_raw, 1073741906, 0, 2, 150, 721]
+[:key_down_raw, 1073741906, 0, 2, 151, 723]
+[:key_down_raw, 1073741906, 0, 2, 152, 725]
+[:key_down_raw, 1073741906, 0, 2, 153, 727]
+[:key_down_raw, 1073741906, 0, 2, 154, 729]
+[:key_down_raw, 1073741906, 0, 2, 155, 731]
+[:key_down_raw, 1073741906, 0, 2, 156, 733]
+[:key_down_raw, 1073741906, 0, 2, 157, 735]
+[:key_down_raw, 1073741906, 0, 2, 158, 737]
+[:key_down_raw, 1073741906, 0, 2, 159, 739]
+[:key_down_raw, 1073741906, 0, 2, 160, 741]
+[:key_down_raw, 1073741906, 0, 2, 161, 743]
+[:key_down_raw, 1073741906, 0, 2, 162, 745]
+[:key_down_raw, 1073741906, 0, 2, 163, 747]
+[:key_down_raw, 1073741906, 0, 2, 164, 749]
+[:key_down_raw, 1073741906, 0, 2, 165, 751]
+[:key_down_raw, 1073741906, 0, 2, 166, 753]
+[:key_down_raw, 1073741906, 0, 2, 167, 755]
+[:key_down_raw, 1073741906, 0, 2, 168, 757]
+[:key_down_raw, 1073741906, 0, 2, 169, 759]
+[:key_down_raw, 1073741906, 0, 2, 170, 761]
+[:key_down_raw, 1073741906, 0, 2, 171, 763]
+[:key_down_raw, 1073741906, 0, 2, 172, 765]
+[:key_down_raw, 1073741906, 0, 2, 173, 767]
+[:key_down_raw, 1073741906, 0, 2, 174, 769]
+[:key_down_raw, 1073741906, 0, 2, 175, 771]
+[:key_down_raw, 1073741906, 0, 2, 176, 773]
+[:key_down_raw, 1073741906, 0, 2, 177, 775]
+[:key_down_raw, 1073741906, 0, 2, 178, 777]
+[:key_down_raw, 1073741906, 0, 2, 179, 779]
+[:key_down_raw, 1073741906, 0, 2, 180, 781]
+[:key_down_raw, 1073741906, 0, 2, 181, 783]
+[:key_down_raw, 1073741904, 0, 2, 182, 784]
+[:key_down_raw, 1073741904, 0, 2, 183, 798]
+[:key_down_raw, 1073741904, 0, 2, 184, 800]
+[:key_down_raw, 1073741904, 0, 2, 185, 802]
+[:key_down_raw, 1073741904, 0, 2, 186, 804]
+[:key_down_raw, 1073741904, 0, 2, 187, 806]
+[:key_down_raw, 1073741904, 0, 2, 188, 810]
+[:key_down_raw, 1073741904, 0, 2, 189, 810]
+[:key_down_raw, 1073741904, 0, 2, 190, 814]
+[:key_down_raw, 1073741904, 0, 2, 191, 815]
+[:key_down_raw, 1073741904, 0, 2, 192, 818]
+[:key_down_raw, 1073741904, 0, 2, 193, 819]
+[:key_down_raw, 1073741904, 0, 2, 194, 822]
+[:key_down_raw, 1073741904, 0, 2, 195, 824]
+[:key_up_raw, 1073741906, 0, 2, 196, 824]
+[:key_down_raw, 1073741904, 0, 2, 197, 825]
+[:key_down_raw, 1073741904, 0, 2, 198, 828]
+[:key_up_raw, 1073741904, 0, 2, 199, 828]
+[:key_down_raw, 96, 0, 2, 200, 870]
+[:key_up_raw, 96, 0, 2, 201, 875]
+[:mouse_move, 802, 100, 2, 202, 933]
+[:mouse_move, 803, 100, 2, 203, 934]
+[:mouse_move, 806, 99, 2, 204, 935]
+[:mouse_move, 808, 98, 2, 205, 936]
+[:mouse_move, 813, 96, 2, 206, 937]
+[:mouse_move, 816, 95, 2, 207, 938]
+[:mouse_move, 824, 93, 2, 208, 939]
+[:mouse_move, 827, 92, 2, 209, 940]
+[:mouse_move, 837, 90, 2, 210, 941]
+[:mouse_move, 843, 90, 2, 211, 942]
+[:mouse_move, 857, 89, 2, 212, 943]
+[:mouse_move, 864, 89, 2, 213, 944]
+[:mouse_move, 874, 88, 2, 214, 945]
+[:mouse_move, 876, 88, 2, 215, 946]
+[:mouse_move, 878, 88, 2, 216, 947]
+[:mouse_move, 881, 87, 2, 217, 948]
+[:mouse_move, 882, 87, 2, 218, 950]
+[:mouse_move, 884, 87, 2, 219, 950]
+[:mouse_move, 885, 87, 2, 220, 951]
+[:mouse_move, 887, 87, 2, 221, 952]
+[:key_down_raw, 13, 0, 2, 222, 1047]
diff --git a/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_down_standing.png b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_down_standing.png
new file mode 100644
index 0000000..9e27489
--- /dev/null
+++ b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_down_standing.png
Binary files differ
diff --git a/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_left_standing.png b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_left_standing.png
new file mode 100644
index 0000000..2fea35b
--- /dev/null
+++ b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_left_standing.png
Binary files differ
diff --git a/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_right_standing.png b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_right_standing.png
new file mode 100644
index 0000000..6f3402e
--- /dev/null
+++ b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_right_standing.png
Binary files differ
diff --git a/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_up_standing.png b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_up_standing.png
new file mode 100644
index 0000000..9ebdca7
--- /dev/null
+++ b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/player/player_up_standing.png
Binary files differ
diff --git a/samples/07_advanced_rendering/08_splitscreen_camera/sprites/rooms/camera_room.png b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/rooms/camera_room.png
new file mode 100644
index 0000000..e0ca375
--- /dev/null
+++ b/samples/07_advanced_rendering/08_splitscreen_camera/sprites/rooms/camera_room.png
Binary files differ