From a3e96f57e36bfd96b753aab3a7fbe28be9bdfcf8 Mon Sep 17 00:00:00 2001 From: realtradam Date: Sun, 25 Apr 2021 18:12:58 -0400 Subject: . --- README.md | 33 +++++++------ assets/houseshadow.png | Bin 10856 -> 0 bytes assets/legacy_player.png | Bin 0 -> 1044 bytes assets/player.png | Bin 1044 -> 0 bytes assets/sprites/peepocomfy-100.png | Bin 4321 -> 0 bytes assets/stand.png | Bin 7792 -> 0 bytes house.rb | 4 +- lib/camera/wrappers/text_wrapper.rb | 28 ++++++++++-- room.rb | 85 ++++++++++++++++++++++------------ run.rb | 89 +++++++++++++++++++++--------------- 10 files changed, 151 insertions(+), 88 deletions(-) delete mode 100644 assets/houseshadow.png create mode 100644 assets/legacy_player.png delete mode 100644 assets/player.png delete mode 100644 assets/sprites/peepocomfy-100.png delete mode 100644 assets/stand.png diff --git a/README.md b/README.md index 2069ab1..f6984c2 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,32 @@ # Ruby2D Camera Demo -`ruby run.rb` to run the demo +`ruby run.rb` to run the demo. ---- - -Controls: +## Controls: WASD to move character -IJKL to move camera -Q/E to rotate camera -R to reset the rotation +Q/E to rotate camera +Hold R to reset the rotation +Space to enter doors + +## How it works: + +A single `Camera` module exists which keeps track of objects that you add to it. When you add an object to the camera it creates a wrapper for the object and 'monkey patches' it onto the object to work with the camera. ---- +Feel free to use any part of this code in your own projects, no credit required(but is appreciated [^; ) -I wanted to make a proof of concept to see how feasible it is to implement a camera system in Ruby2D. Turns out it is very feasible :D +## How to use the camera in your own code: -How it works: +Copy the `lib/camera/` directory into your ruby project and then in your code simply ```require_relative 'camera/camera'``` at the top. In your `Update do` loop you must add ```Camera.redraw``` at the bottom(this is so that the camera applies any changes you tell it to do). Your camera is now ready to use! -A single `Camera` module exists which keeps track of objects that you add to it. When you add an object to the camera (currently only triangles) it creates a wrapper for the object and modifys it to work with the camera. +To add an object to the camera simply do ```Camera << @your_object``` and the camera will do its magic on your object. Only the various shape/image/text/line/sprite/etc. from Ruby2D are supported. +Whenever an object is wrapped by the camera it gets `x` and `y` methods if it does not already have them which you can use to move the object around in the camera. The text object also gets a `center` method which you can set to true if you wish the origin of text to be its center. Otherwise the origin of all objects is the top left corner. Other then these methods mentioned, object behave as expected within the context of the camera. -If you want to use this little demo in your own projects feel free to do so! All you need is the camera.rb file and then just `require` or `require_relative` it into your project. -See the code as an example for how it is used. +When unloading an object, make sure to also remove it from the Camera or else it will attempt to update it when it is Nil. To do this use the following: `Camera.remove(@your_object)` -Credit is appreciated but not required :) +To manipulate the camera there are 4 variables you can use: +- `Camera.zoom` Default: 1. This is a multiplier for how much you want the camera to be zoomed in(e.g 2 is 2x zoom, 0.5 is 0.5x zoom) +- `Camera.x` and `Camera.y` Default: 0. This are the position of the camera in the "world" +- `Camera.angle` Default: 0. This is the angle of how much the camera is rotated(in degrees). It ranges from 0-359. Giving values outside of this range will automagically convert them to fit within the 0-359 range. diff --git a/assets/houseshadow.png b/assets/houseshadow.png deleted file mode 100644 index d860b9b..0000000 Binary files a/assets/houseshadow.png and /dev/null differ diff --git a/assets/legacy_player.png b/assets/legacy_player.png new file mode 100644 index 0000000..485e972 Binary files /dev/null and b/assets/legacy_player.png differ diff --git a/assets/player.png b/assets/player.png deleted file mode 100644 index 485e972..0000000 Binary files a/assets/player.png and /dev/null differ diff --git a/assets/sprites/peepocomfy-100.png b/assets/sprites/peepocomfy-100.png deleted file mode 100644 index 6d8812d..0000000 Binary files a/assets/sprites/peepocomfy-100.png and /dev/null differ diff --git a/assets/stand.png b/assets/stand.png deleted file mode 100644 index 2c7038d..0000000 Binary files a/assets/stand.png and /dev/null differ diff --git a/house.rb b/house.rb index 850bea8..1da0d58 100644 --- a/house.rb +++ b/house.rb @@ -90,8 +90,8 @@ class House y = @y + 160 if character.x >= x && character.x <= (x + (character.width * 2)) && character.y > y && character.y <= (y + (character.height * 2)) Text.new('Press Space To Enter House', - x: x - 10, - y: y + 20, + x: x + 70, + y: y + 30, color: 'white', z: 98, size: 25.0) diff --git a/lib/camera/wrappers/text_wrapper.rb b/lib/camera/wrappers/text_wrapper.rb index 56b35ed..ad96881 100644 --- a/lib/camera/wrappers/text_wrapper.rb +++ b/lib/camera/wrappers/text_wrapper.rb @@ -3,19 +3,31 @@ module Camera # Wraps existing variables as well as adding new methods # so that it can be handled by the Camera Module + # TODO: note that text could not be resized at the current iteration + # of Ruby2D so the math needs to be changed compensate for this. + # When Ruby2D gets updated to allow text resizing the math will need + # to be corrected again(see image_wrapper.rb for reference, that has + # math that allows for resizing) module TextWrapped + @center = false + # Recalculates real coordiantes # Use after changing variables def redraw angle = Camera.angle * (Math::PI / 180) half_width = Window.width * 0.5 half_height = Window.height * 0.5 - offset_x = x + (width / 2) - offset_y = y + (height / 2) + if center + offset_y = y + (Camera.zoom / 2) + offset_x = x + (Camera.zoom / 2) + else + offset_x = x + (width / Camera.zoom / 2) + offset_y = y + (height / Camera.zoom / 2) + end @x = (((offset_x - Camera.x) * Math.cos(angle)) - ((offset_y - Camera.y) * Math.sin(angle))) \ - * Camera.zoom + half_width - (width * Camera.zoom / 2) + * Camera.zoom + half_width - (width / 2) @y = (((offset_x - Camera.x) * Math.sin(angle)) + ((offset_y - Camera.y) * Math.cos(angle))) \ - * Camera.zoom + half_height - (height * Camera.zoom / 2) + * Camera.zoom + half_height - (height / 2) @rotate = rotate + Camera.angle @size = size * Camera.zoom end @@ -60,5 +72,13 @@ module Camera def size=(size) @virtual_size = size end + + def center + @center + end + + def center=(center) + @center = center + end end end diff --git a/room.rb b/room.rb index 5811dc8..0366b36 100644 --- a/room.rb +++ b/room.rb @@ -2,81 +2,106 @@ # Is a house class Room - def debug - @debug - end def initialize(x, y) @objects = [] @x = x @y = y + roomy = 155 @objects.push Square.new(x: 125 + x, y: 230 + y, size: 50, - color: 'blue') + color: 'blue', + z: 3) @objects.push Circle.new(x: 125 + x, y: 205 + y, radius: 25, - color: 'blue') + sectors: 64, + color: 'blue', + z: 3) @objects.push Quad.new(x1: 50 + x, - y1: 130 + y, + y1: 130 + y + roomy, x2: 125 + x, - y2: 180 + y, + y2: 180 + y + roomy, x3: 325 + x, - y3: 180 + y, + y3: 180 + y + roomy, x4: 250 + x, - y4: 130 + y, + y4: 130 + y + roomy, color: 'aqua', z: 1) @objects.push Quad.new(x1: 50 + x, - y1: 45 + y, + y1: 45 + y + roomy, x2: 50 + x, - y2: 125 + y, + y2: 125 + y + roomy, x3: 250 + x, - y3: 125 + y, + y3: 125 + y + roomy, x4: 250 + x, - y4: 45 + y, + y4: 45 + y + roomy, color: 'orange', z: 1) @objects.push Quad.new(x1: 255 + x, - y1: 45 + y, - x2: 255 + x, - y2: 125 + y, - x3: 330 + x, - y3: 175 + y, - x4: 330 + x, - y4: 95 + y, - color: 'olive', - z: 1) + y1: 45 + y + roomy, + x2: 255 + x, + y2: 125 + y + roomy, + x3: 330 + x, + y3: 175 + y + roomy, + x4: 330 + x, + y4: 95 + y + roomy, + color: 'olive', + z: 1) @objects.push Sprite.new('./assets/sprites/blobdance-128.png', x: 250 + x, - y: 135 + y, + y: 135 + y + roomy, width: 40, height: 40, clip_width: 128, loop: true, time: 24, - z: 2) + z: 5) @objects.last.play + @objects.push Image.new( + 'assets/blobshadow.png', + x: 250 + x - 2 - 5, + y: 135 + y + roomy + 42 - 15, + width: 52, + height: 10, + z: 4 + ) @objects.push Sprite.new('./assets/sprites/dance2-112.png', x: 95 + x, - y: 115 + y, + y: 115 + y + roomy, width: 40, height: 40, clip_width: 112, loop: true, time: 13, - z: 2) + z: 5) @objects.last.play + @objects.push Image.new( + 'assets/blobshadow.png', + x: 95 + x - 2 - 5, + y: 115 + y + roomy + 42 - 10, + width: 52, + height: 10, + z: 4 + ) @objects.push Sprite.new('./assets/sprites/dancer-128.png', x: 175 + x, - y: 120 + y, + y: 120 + y + roomy, width: 45, height: 45, clip_width: 128, loop: true, time: 60, - z: 2) + z: 5) @objects.last.play + @objects.push Image.new( + 'assets/blobshadow.png', + x: 175 + x - 2 - 5, + y: 120 + y + roomy + 42 - 5, + width: 52, + height: 10, + z: 4 + ) @objects.each do |item| Camera << item end @@ -94,8 +119,8 @@ class Room y = @y + 160 if character.x >= x && character.x <= (x + (character.width * 2)) && character.y > y && character.y <= (y + (character.height * 2)) Text.new('Press Space To Exit House', - x: x - 10, - y: y + 20, + x: x + 70, + y: y + 30, color: 'white', z: 98, size: 25.0) diff --git a/run.rb b/run.rb index 3899c83..5197978 100644 --- a/run.rb +++ b/run.rb @@ -28,11 +28,13 @@ Window.set(icon: './assets/blobcoolthink.png', 'assets/blobshadow.png', width: 52, height: 10, - z: 1 + z: 4 ) Camera << @shadow @player.play animation: :walk, loop: true Camera << @player + +# UI Rectangle.new( width: 350, height: 135, @@ -88,8 +90,8 @@ Rectangle.new( @speed = 5 # Initializing -player_movement_x = 0 -player_movement_y = 0 +@player_movement_x = 0 +@player_movement_y = 0 @pressed_space = false @scene_transition_into = false @scene_transition_out = false @@ -99,62 +101,68 @@ player_movement_y = 0 on :key do |event| if event.key == 'w' - player_movement_y -= @speed unless @scene_transition_into || @scene_transition_out + @player_movement_y -= @speed unless @scene_transition_into || @scene_transition_out end if event.key == 's' - player_movement_y += @speed unless @scene_transition_into || @scene_transition_out + @player_movement_y += @speed unless @scene_transition_into || @scene_transition_out end if event.key == 'd' - player_movement_x += @speed unless @scene_transition_into || @scene_transition_out + @player_movement_x += @speed unless @scene_transition_into || @scene_transition_out end if event.key == 'a' - player_movement_x -= @speed unless @scene_transition_into || @scene_transition_out + @player_movement_x -= @speed unless @scene_transition_into || @scene_transition_out end if event.key == 'space' @pressed_space = true unless @scene_transition_into || @scene_transition_out end if event.key == 'q' - Camera.angle += 1 + Camera.angle += 1 unless @scene_transition_into || @scene_transition_out end if event.key == 'e' - Camera.angle -= 1 - end - if event.key == 'z' - Camera.zoom *= 1.015 - end - if event.key == 'x' - Camera.zoom *= 0.985 + Camera.angle -= 1 unless @scene_transition_into || @scene_transition_out + end + if event.key == 'r' + unless @scene_transition_into || @scene_transition_out || Camera.angle.zero? + if Camera.angle <= 180 + if Camera.angle > 10 + Camera.angle -= 10 + else + Camera.angle -=1 + end + elsif + if Camera.angle < 350 + Camera.angle += 10 + else + Camera.angle += 1 + end + end + end end end -=begin -Camera << Text.new('rotate me to see how if it works', - x: 500, - y: 500, - z: 99) -=end + update do - if (@player.x > 2371 && player_movement_x.positive?) || (@player.x.negative? && player_movement_x.negative?) - player_movement_x = 0 + if (@player.x > 2371 && @player_movement_x.positive?) || (@player.x.negative? && @player_movement_x.negative?) + @player_movement_x = 0 end - if (@player.y > 1608 && player_movement_y.positive?) || (@player.y.negative? && player_movement_y.negative?) - player_movement_y = 0 + if (@player.y > 1608 && @player_movement_y.positive?) || (@player.y.negative? && @player_movement_y.negative?) + @player_movement_y = 0 end - if !player_movement_y.zero? == !player_movement_x.zero? - player_movement_x /= 1.4141 - player_movement_y /= 1.4141 + if !@player_movement_y.zero? == !@player_movement_x.zero? + @player_movement_x /= 1.4141 + @player_movement_y /= 1.4141 end - @player.x += player_movement_x - @player.y += player_movement_y - if player_movement_x.negative? + @player.x += @player_movement_x + @player.y += @player_movement_y + if @player_movement_x.negative? @player.play animation: :walk, loop: true - elsif player_movement_x.positive? || !player_movement_y.zero? + elsif @player_movement_x.positive? || !@player_movement_y.zero? @player.play animation: :walk, loop: true, flip: :vertical else @player.play animation: :stand end if !@scene_transition_into && !@scene_transition_out - Camera.zoom = (-[Math.sqrt(((@player.x + (@player.width / 2) - Camera.x)**2) + ((@player.y + (@player.width / 2) - Camera.y)**2)), 350].min * 0.004) + 2 + Camera.zoom += ((-[Math.sqrt(((@player.x + (@player.width / 2) - Camera.x)**2) + ((@player.y + (@player.width / 2) - Camera.y)**2)), 350].min * 0.004) + 2 - Camera.zoom) * 0.25 Camera.x += (@player.x + (@player.width / 2) - Camera.x) * 0.025 Camera.y += (@player.y + (@player.height / 2)- Camera.y) * 0.025 elsif @scene_transition_into @@ -180,7 +188,7 @@ update do Camera.x += (@player.x + (@player.width / 2) - Camera.x) * 0.25 Camera.y += (@player.y + (@player.height / 2) - Camera.y) * 0.25 elsif @scene_transition_out - if !(Camera.zoom <= 2.1 && Camera.angle.zero?) + if !((Camera.zoom <= (@zoom_transition * 1.001)) && (Camera.angle == @angle_transition)) Camera.zoom /= 1.05 Camera.angle -= 5 else @@ -217,17 +225,22 @@ update do else @house_text = @house.visted_by?(@player) end - Camera << @house_text unless @house_text.nil? - if !@house_text.nil? && @pressed_space + unless @house_text.nil? + Camera << @house_text + @house_text.center = true + end + if !@house_text.nil? && @pressed_space && !@scene_transition_into && !@scene_transition_out @scene_transition_into = true + @angle_transition = Camera.angle + @zoom_transition = Camera.zoom end @ui_pos_cam.text = "Camera Position: #{Camera.x.round(1)}, #{Camera.y.round(1)}" @ui_pos_ply.text = "Player Position: #{@player.x.round(1)}, #{@player.y.round(1)}" @ui_zoom.text = "Zoom: #{Camera.zoom.round(3)}" @ui_fps.text = "FPS: #{Window.fps.round(2)}" @ui_rotation.text = "Angle: #{Camera.angle}" - player_movement_x = 0 - player_movement_y = 0 + @player_movement_x = 0 + @player_movement_y = 0 @pressed_space = false Camera.redraw -- cgit v1.2.3