summaryrefslogtreecommitdiffhomepage
path: root/samples/07_advanced_rendering/08_splitscreen_camera/app
diff options
context:
space:
mode:
Diffstat (limited to 'samples/07_advanced_rendering/08_splitscreen_camera/app')
-rw-r--r--samples/07_advanced_rendering/08_splitscreen_camera/app/main.rb396
1 files changed, 396 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