Initial Commit

This commit is contained in:
2018-06-07 10:03:07 -05:00
commit b4852fbbd6
22 changed files with 1255 additions and 0 deletions

15
lib/cyberarm_engine.rb Normal file
View File

@@ -0,0 +1,15 @@
require "gosu"
require_relative "cyberarm_engine/version"
require_relative "cyberarm_engine/game_object"
require_relative "cyberarm_engine/game_state"
require_relative "cyberarm_engine/engine"
require_relative "cyberarm_engine/objects/text"
require_relative "cyberarm_engine/objects/multi_line_text"
require_relative "cyberarm_engine/ui/button"
require_relative "cyberarm_engine/ui/check_box"
require_relative "cyberarm_engine/ui/input"
require_relative "cyberarm_engine/ui/container"

View File

@@ -0,0 +1,80 @@
module CyberarmEngine
class Engine < Gosu::Window
attr_accessor :show_cursor
attr_reader :current_game_state, :last_game_state, :last_frame_time
def self.now
Gosu.milliseconds
end
def self.dt
$window.last_frame_time/1000.0
end
def initialize(width = 800, height = 600, fullscreen = false, update_interval = 1000.0/60)
@show_cursor = false
super(width, height, fullscreen, update_interval)
$window = self
@last_frame_time = Gosu.milliseconds-1
@current_frame_time = Gosu.milliseconds
self.caption = "CyberarmEngine #{CyberarmEngine::VERSION} #{Gosu.language}"
setup if defined?(setup)
end
def draw
if @current_game_state.is_a?(GameState)
@current_game_state.draw
end
end
def update
if @current_game_state.is_a?(GameState)
@current_game_state.update
end
@last_frame_time = Gosu.milliseconds-@current_frame_time
@current_frame_time = Gosu.milliseconds
end
def needs_cursor?
@show_cursor
end
def dt
@last_frame_time/1000.0
end
def button_up(id)
@current_game_state.button_up(id) if @current_game_state
end
def push_game_state(klass, options={})
@last_game_state = @current_game_state if @current_game_state
if klass.instance_of?(klass.class) && defined?(klass.options)
@current_game_state = klass
else
klass.new(options)
end
end
def set_game_state(klass_instance)
@current_game_state = klass_instance
end
def previous_game_state
# current_game_state = @current_game_state
# @current_game_state = @last_frame_time
# @last_game_state = current_game_state
@last_game_state
end
# Sourced from https://gist.github.com/ippa/662583
def draw_circle(cx,cy,r, z = 9999,color = Gosu::Color::GREEN, step = 10)
0.step(360, step) do |a1|
a2 = a1 + step
draw_line(cx + Gosu.offset_x(a1, r), cy + Gosu.offset_y(a1, r), color, cx + Gosu.offset_x(a2, r), cy + Gosu.offset_y(a2, r), color, z)
end
end
end
end

View File

@@ -0,0 +1,302 @@
module CyberarmEngine
class GameObject
INSTANCES = []
IMAGES = {}
SAMPLES= {}
Vertex = Struct.new(:x, :y)
attr_accessor :image, :x, :y, :z, :angle, :center_x, :center_y, :scale_x, :scale_y,
:color, :alpha, :mode, :options, :paused, :radius, :last_x, :last_y
attr_reader :world_center_point
def initialize(options={})
if options[:auto_manage] || options[:auto_manage] == nil
INSTANCES.push(self)
$window.current_game_state.add_game_object(self)
end
@options = options
@image = options[:image] ? image(options[:image]) : nil
@x = options[:x] ? options[:x] : 0
@y = options[:y] ? options[:y] : 0
@z = options[:z] ? options[:z] : 0
@last_x = 0
@last_y = 0
@angle = options[:angle] ? options[:angle] : 0
@center_x = options[:center_x] ? options[:center_x] : 0.5
@center_y = options[:center_y] ? options[:center_y] : 0.5
@scale_x = options[:scale_x] ? options[:scale_x] : 1
@scale_y = options[:scale_y] ? options[:scale_y] : 1
@color = options[:color] ? options[:color] : Gosu::Color.argb(0xff_ffffff)
@alpha = options[:alpha] ? options[:alpha] : 255
@mode = options[:mode] ? options[:mode] : :default
@paused = false
@speed = 0
@debug_color = Gosu::Color::GREEN
@world_center_point = Vertex.new(0,0)
setup
@debug_text = MultiLineText.new("", color: @debug_color, y: self.y-(self.height*self.scale), z: 9999)
@debug_text.x = self.x
if @radius == 0 || @radius == nil
@radius = options[:radius] ? options[:radius] : defined?(@image.width) ? ((@image.width+@image.height)/4)*scale : 1
end
end
def draw
if @image
@image.draw_rot(@x, @y, @z, @angle, @center_x, @center_y, @scale_x, @scale_y, @color, @mode)
end
if $debug
show_debug_heading if $heading
$window.draw_circle(self.x, self.y, radius, 9999, @debug_color)
if @debug_text.text != ""
$window.draw_rect(@debug_text.x-10, (@debug_text.y-10), @debug_text.width+20, @debug_text.height+20, Gosu::Color.rgba(0,0,0,200), 9999)
@debug_text.draw
end
end
end
def update
end
def image(image_path)
image = nil
GameObject::IMAGES.detect do |img, instance|
if img == image_path
image = instance
true
end
end
unless image
instance = Gosu::Image.new(image_path)
GameObject::IMAGES[image_path] = instance
image = instance
end
return image
end
def sample(sample_path)
sample = nil
GameObject::SAMPLES.detect do |smp, instance|
if smp == sample_path
sample = instance
true
end
end
unless sample
instance = Gosu::Sample.new(sample_path)
GameObject::SAMPLES[sample_path] = instance
sample = instance
end
return sample
end
def debug_text(text)
@debug_text.text = text
end
def update_debug_text
@debug_text.x = self.x-(@debug_text.width/2)
@debug_text.y = self.y-((self.height)*self.scale)
end
def scale
if @scale_x == @scale_y
return @scale_x
else
false
# maths?
end
end
def scale=(int)
self.scale_x = int
self.scale_y = int
self.radius = ((@image.width+@image.height)/4)*self.scale
end
def x=(i)
@last_x = @x
@x = i
end
def y=(i)
@last_y = @y
@y = i
end
def visible
true
# if _x_visible
# if _y_visible
# true
# else
# false
# end
# else
# false
# end
end
def _x_visible
self.x.between?(($window.width/2)-(@world_center_point.x), ($window.width/2)+@world_center_point.x) ||
self.x.between?(((@world_center_point.x)-$window.width/2), ($window.width/2)+@world_center_point.x)
end
def _y_visible
self.y.between?(($window.height/2)-(@world_center_point.y), ($window.height/2)+@world_center_point.y) ||
self.y.between?((@world_center_point.y)-($window.height/2), ($window.height/2)+@world_center_point.y)
end
def heading(ahead_by = 100, object = nil, angle_only = false)
direction = ((Gosu.angle(@last_x, @last_y, self.x, self.y)) - 90.0) * (Math::PI / 180.0)
ahead_by+object.speed*Engine.dt if object
_x = @x+(ahead_by*Math.cos(direction))
_y = @y+(ahead_by*Math.sin(direction))
return direction if angle_only
return Vertex.new(_x, _y) unless angle_only
end
def show_debug_heading
_heading = heading
$window.draw_line(x, y, @debug_color, _heading.x, _heading.y, @debug_color, 9999)
end
def width
@image ? @image.width : 0
end
def height
@image ? @image.height : 0
end
def pause
@paused = true
end
def unpause
@paused = false
end
def rotate(int)
self.angle+=int
self.angle%=360
end
def alpha=int # 0-255
@alpha = int
@alpha = 255 if @alpha > 255
@color = Gosu::Color.rgba(@color.red, @color.green, @color.blue, int)
end
def draw_rect(x, y, width, height, color, z = 0)
$window.draw_rect(x,y,width,height,color,z)
end
def button_up(id)
end
def button_down?(id)
end
def find_closest(game_object_class)
best_object = nil
best_distance = 100_000_000_000 # Huge default number
game_object_class.all.each do |object|
distance = Gosu::distance(self.x, self.y, object.x, object.y)
if distance <= best_distance
best_object = object
best_distance = distance
end
end
return best_object
end
def look_at(object)
# TODO: Implement
end
def circle_collision?(object)
distance = Gosu.distance(self.x, self.y, object.x, object.y)
if distance <= self.radius+object.radius
true
else
false
end
end
# Duplication... so DRY.
def each_circle_collision(object, resolve_with = :width, &block)
if object.class != Class && object.instance_of?(object.class)
$window.current_game_state.game_objects.select {|i| i.class == object.class}.each do |o|
distance = Gosu.distance(self.x, self.y, object.x, object.y)
if distance <= self.radius+object.radius
block.call(o, object) if block
end
end
else
list = $window.current_game_state.game_objects.select {|i| i.class == object}
list.each do |o|
next if self == o
distance = Gosu.distance(self.x, self.y, o.x, o.y)
if distance <= self.radius+o.radius
block.call(self, o) if block
end
end
end
end
def destroy
INSTANCES.delete(self)
if $window.current_game_state
$window.current_game_state.game_objects.each do |o|
if o.is_a?(self.class) && o == self
$window.current_game_state.game_objects.delete(o)
end
end
end
end
# NOTE: This could be implemented more reliably
def self.all
INSTANCES.select {|i| i.class == self}
end
def self.each_circle_collision(object, resolve_with = :width, &block)
if object.class != Class && object.instance_of?(object.class)
$window.current_game_state.game_objects.select {|i| i.class == self}.each do |o|
distance = Gosu.distance(o.x, o.y, object.x, object.y)
if distance <= o.radius+object.radius
block.call(o, object) if block
end
end
else
lista = $window.current_game_state.game_objects.select {|i| i.class == self}
listb = $window.current_game_state.game_objects.select {|i| i.class == object}
lista.product(listb).each do |o, o2|
next if o == o2
distance = Gosu.distance(o.x, o.y, o2.x, o2.y)
if distance <= o.radius+o2.radius
block.call(o, o2) if block
end
end
end
end
def self.destroy_all
INSTANCES.clear
if $window.current_game_state
$window.current_game_state.game_objects.each do |o|
if o.is_a?(self.class)
$window.current_game_state.game_objects.delete(o)
end
end
end
end
end
end

View File

@@ -0,0 +1,64 @@
class GameState
SCALE_X_BASE = 1920.0
SCALE_Y_BASE = 1080.0
attr_accessor :options, :global_pause
attr_reader :game_objects
def initialize(options={})
$window.set_game_state(self)
@options = options unless @options
@game_objects = []
@global_pause = false
setup
@_4ship = Ship.all.first if Ship.all.is_a?(Array)
end
def setup
end
def draw
# count = 0
@game_objects.each do |o|
o.draw if o.visible
# p o.class if o.visible
# count+=1 if o.visible
end
# puts "Num visible objects: #{count} of #{@game_objects.count}"
end
def update
@game_objects.each do |o|
unless o.paused || @global_pause
o.world_center_point.x = @_4ship.x
o.world_center_point.y = @_4ship.y
o.update
o.update_debug_text if $debug
end
end
end
def destroy
@options = nil
@game_objects = nil
end
def button_up(id)
@game_objects.each do |o|
o.button_up(id) unless o.paused
end
end
def push_game_state(klass, options={})
$window.push_game_state(klass, options)
end
def draw_rect(x, y, width, height, color, z = 0)
$window.draw_rect(x,y,width,height,color,z)
end
def add_game_object(object)
@game_objects << object
end
end

View File

@@ -0,0 +1,59 @@
module CyberarmEngine
class MultiLineText
attr_accessor :options, :x, :y, :width, :height
def initialize(text, options={})
@texts = []
text.split("\n").each_with_index do |line, i|
_options = options
_options[:y]+=_options[:size]
@texts << Text.new(line, _options)
end
@options = options
@x = @texts.first ? @texts.first.x : 0
@y = @texts.first ? @texts.first.y : 0
@width = 0
@height = 0
calculate_boundry
end
def draw
@texts.each(&:draw)
end
def text
string = ""
@texts.each {|t| string << t.text}
return string
end
def text=(text)
text.split("\n").each_with_index do |line, i|
if @texts[i]
@texts[i].text = line
else
@texts << Text.new(line, @options)
end
end
calculate_boundry
end
def x=(int)
@x = int
@texts.each {|t| t.x = int}
end
def y=(int)
@y = int
@texts.each_with_index {|t, i| t.y=int+(i*t.size)}
end
def calculate_boundry
@width = 0
@height= 0
@texts.each {|t| @width = t.width if t.width > @width}
@texts.each {|t| @height+=t.height}
end
end
end

View File

@@ -0,0 +1,95 @@
module CyberarmEngine
class Text
CACHE = {}
attr_accessor :text, :x, :y, :z, :size, :factor_x, :factor_y, :color, :shadow, :shadow_size, :options
attr_reader :textobject
def initialize(text, options={})
@text = text || ""
@options = options
@size = options[:size] || 18
@font = options[:font] || Gosu.default_font_name
@x = options[:x] || 0
@y = options[:y] || 0
@z = options[:z] || 1025
@factor_x = options[:factor_x] || 1
@factor_y = options[:factor_y] || 1
@color = options[:color] || Gosu::Color::WHITE
@alignment= options[:alignment] || nil
@shadow = true if options[:shadow] == true
@shadow = false if options[:shadow] == false
@shadow = true if options[:shadow] == nil
@shadow_size = options[:shadow_size] ? options[:shadow_size] : 1
@shadow_alpha= options[:shadow_alpha] ? options[:shadow_alpha] : 30
@textobject = check_cache(@size, @font)
if @alignment
case @alignment
when :left
@x = 0+BUTTON_PADDING
when :center
@x = ($window.width/2)-(@textobject.text_width(@text)/2)
when :right
@x = $window.width-BUTTON_PADDING-@textobject.text_width(@text)
end
end
return self
end
def check_cache(size, font_name)
available = false
font = nil
if CACHE[size]
if CACHE[size][font_name]
font = CACHE[size][font_name]
available = true
else
available = false
end
else
available = false
end
unless available
font = Gosu::Font.new(@size, name: @font)
CACHE[@size] = {} unless CACHE[@size].is_a?(Hash)
CACHE[@size][@font] = font
end
return font
end
def width
textobject.text_width(@text)
end
def height
textobject.height
end
def draw
if @shadow && !ARGV.join.include?("--no-shadow")
_color = Gosu::Color.rgba(@color.red, @color.green, @color.blue, @shadow_alpha) if @shadow_alpha <= @color.alpha
_color = Gosu::Color.rgba(@color.red, @color.green, @color.blue, @color.alpha) unless @shadow_alpha <= @color.alpha
@textobject.draw(@text, @x-@shadow_size, @y, @z, @factor_x, @factor_y, _color)
@textobject.draw(@text, @x-@shadow_size, @y-@shadow_size, @z, @factor_x, @factor_y, _color)
@textobject.draw(@text, @x, @y-@shadow_size, @z, @factor_x, @factor_y, _color)
@textobject.draw(@text, @x+@shadow_size, @y-@shadow_size, @z, @factor_x, @factor_y, _color)
@textobject.draw(@text, @x, @y+@shadow_size, @z, @factor_x, @factor_y, _color)
@textobject.draw(@text, @x-@shadow_size, @y+@shadow_size, @z, @factor_x, @factor_y, _color)
@textobject.draw(@text, @x+@shadow_size, @y, @z, @factor_x, @factor_y, _color)
@textobject.draw(@text, @x+@shadow_size, @y+@shadow_size, @z, @factor_x, @factor_y, _color)
end
@textobject.draw(@text, @x, @y, @z, @factor_x, @factor_y, @color)
end
def update; end
end
end

View File

@@ -0,0 +1,122 @@
module CyberarmEngine
BUTTON_TEXT_COLOR = Gosu::Color::WHITE
BUTTON_TEXT_ACTIVE_COLOR = Gosu::Color::BLACK
BUTTON_COLOR = Gosu::Color.rgb(12,12,12)
BUTTON_HOVER_COLOR = Gosu::Color.rgb(100, 100, 100)
BUTTON_ACTIVE_COLOR = Gosu::Color.rgb(50, 50, 50)
BUTTON_TEXT_SIZE = 20
BUTTON_PADDING = 10
class Button
attr_accessor :text, :x, :y, :offset_x, :offset_y, :tooltip, :block
def initialize(text, x, y, auto_manage = true, tooltip = "", &block)
@text = Text.new(text, x: x, y: y, size: BUTTON_TEXT_SIZE, color: BUTTON_TEXT_COLOR, shadow: true)
@tooltip=Text.new(tooltip, x: x, y: y-(height/4*3), z: 10_000, size: BUTTON_TEXT_SIZE, color: BUTTON_TEXT_COLOR, shadow: false)
@x = x
@y = y
_x_ = @x+(@text.textobject.text_width(@text.text)/2)-(@tooltip.textobject.text_width(@tooltip.text)/2)
@tooltip.x = _x_+BUTTON_PADDING
auto_adjust_tooltip_position
@offset_x, @offset_y = 0, 0
if block
@block = Proc.new{yield(self)}
else
@block = Proc.new {}
end
Window.instance.elements.push(self) if auto_manage
return self
end
def update_position_toolip
_x_ = @x+(@text.textobject.text_width(@text.text)/2)-(@tooltip.textobject.text_width(@tooltip.text)/2)
@tooltip.x = _x_+BUTTON_PADDING
auto_adjust_tooltip_position
end
def auto_adjust_tooltip_position
if @tooltip.x <= 1
@tooltip.x = 2
elsif @tooltip.x+@tooltip.textobject.text_width(@tooltip.text) > $window.width-(BUTTON_PADDING+1)
@tooltip.x = $window.width-@tooltip.textobject.text_width(@tooltip.text)
end
end
def draw
@text.draw
$window.draw_rect(@x, @y, width, height, BUTTON_COLOR)
if mouse_clicked_on_check
$window.draw_rect(@x+1, @y+1, width-2, height-2, BUTTON_ACTIVE_COLOR)
elsif mouse_over?
$window.draw_rect(@x+1, @y+1, width-2, height-2, BUTTON_HOVER_COLOR)
show_tooltip
else
$window.draw_rect(@x+1, @y+1, width-2, height-2, BUTTON_COLOR)
end
end
def update
@text.x = @x+BUTTON_PADDING
@text.y = @y+BUTTON_PADDING
end
def button_up(id)
case id
when Gosu::MsLeft
click_check
end
end
def click_check
if mouse_over?
puts "Clicked: #{@text.text}"
@block.call if @block.is_a?(Proc)
end
end
def mouse_clicked_on_check
if mouse_over? && Gosu.button_down?(Gosu::MsLeft)
true
end
end
def mouse_over?
if $window.mouse_x.between?(@x+@offset_x, @x+@offset_x+width)
if $window.mouse_y.between?(@y+@offset_y, @y+@offset_y+height)
true
end
end
end
def show_tooltip
if @tooltip.text != ""
x = @tooltip.x-BUTTON_PADDING
$window.draw_rect(x, @y-height, width(@tooltip), height(@tooltip), BUTTON_ACTIVE_COLOR, 9_999)
$window.draw_rect(x-1, @y-height-1, width(@tooltip)+2, height(@tooltip)+2, Gosu::Color::WHITE, 9_998)
@tooltip.draw
end
end
def width(text_object = @text)
text_object.textobject.text_width(text_object.text)+BUTTON_PADDING*2
end
def height(text_object = @text)
text_object.textobject.height+BUTTON_PADDING*2
end
def set_offset(x, y)
@offset_x, @offset_y = x, y
end
def update_text(string)
@text.text = string
end
end
end

View File

@@ -0,0 +1,73 @@
module CyberarmEngine
class CheckBox
SIZE = 22
attr_accessor :x, :y, :checked
attr_reader :text
def initialize(x, y, checked = false, size = CheckBox::SIZE)
@x, @y = x, y
@checked = checked
@size = size
@text = Text.new("", false, x: x, y: y, size: size, color: BUTTON_TEXT_COLOR, shadow: true)
return self
end
def x=(int)
@x = int
@text.x = int
end
def y=(int)
@y = int
@text.y = int
end
def draw
$window.draw_rect(@x, @y, width, height, Gosu::Color::BLACK)
if mouse_over?
$window.draw_rect(@x+1, @y+1, width-2, height-2, BUTTON_HOVER_COLOR)
else
if @checked
$window.draw_rect(@x+1, @y+1, width-2, height-2, BUTTON_ACTIVE_COLOR)
else
$window.draw_rect(@x+1, @y+1, width-2, height-2, BUTTON_COLOR)
end
end
if @checked
@text.draw
end
end
def update
@text.x = @x+BUTTON_PADDING
@text.y = @y+BUTTON_PADDING
end
def button_up(id)
if mouse_over? && id == Gosu::MsLeft
if @checked
@checked = false
else
@checked = true
end
end
end
def mouse_over?
if $window.mouse.x.between?(@x, @x+width)
if $window.mouse.y.between?(@y, @y+height)
true
end
end
end
def width(text_object = @text)
text_object.textobject.text_width(text_object.text)+BUTTON_PADDING*2
end
def height(text_object = @text)
text_object.textobject.height+BUTTON_PADDING*2
end
end
end

View File

@@ -0,0 +1,157 @@
module CyberarmEngine
class Container
attr_accessor :text_color
attr_reader :elements, :x, :y, :width, :height, :options
attr_reader :scroll_x, :scroll_y, :internal_width, :internal_height
def initialize(x = 0, y = 100, width = $window.width, height = $window.height, options = {})
@x, @y, @width, @height, @internal_width, @internal_height = x, y, width, height-y, width, height-y
@scroll_x, @scroll_y = 0, 0
@scroll_speed = 10
puts "#{self.class}: width #{width}, height #{@height}"
@options = {}
@allow_recreation_on_resize = true
@text_color = options[:text_color] || Gosu::Color::WHITE
@elements = []
if defined?(self.setup); setup; end
end
def draw
Gosu.clip_to(x, y, width, height) do
Gosu.translate(scroll_x, scroll_y) do
@elements.each(&:draw)
end
end
end
def update
@elements.each(&:update)
end
def button_up(id)
if $window.mouse_x.between?(@x, @x+@width)
if $window.mouse_y.between?(@y, @y+@height)
case id
when Gosu::MsWheelUp
@scroll_y+=@scroll_speed
@scroll_y = 0 if @scroll_y > 0
@elements.each {|e| e.set_offset(@scroll_x, @scroll_y) if e.is_a?(Button) }
when Gosu::MsWheelDown
@scroll_y-=@scroll_speed
if $window.height-@internal_height-y > 0
@scroll_y = 0
p "H: #{@height-@internal_height}", "Y: #{@scroll_y}"
else
@scroll_y = @height-@internal_height if @scroll_y <= @height-@internal_height
end
@elements.each {|e| e.set_offset(@scroll_x, @scroll_y) if e.is_a?(Button) }
end
end
end
@elements.each {|e| if defined?(e.button_up); e.button_up(id); end}
end
def build(&block)
yield(self)
end
def text(text, x, y, size = 18, color = self.text_color, alignment = nil, font = nil)
relative_x = @x+x
relative_y = @y+y
_text = Text.new(text, x: relative_x, y: relative_y, size: size, color: color, alignment: alignment, font: font)
@elements.push(_text)
if _text.y-(_text.height*2) > @internal_height
@internal_height+=_text.height
end
return _text
end
def button(text, x, y, tooltip = "", &block)
relative_x = @x+x
relative_y = @y+y
_button = Button.new(text, relative_x, relative_y, false, tooltip) { if block.is_a?(Proc); block.call; end }
@elements.push(_button)
if _button.y-(_button.height*2) > @internal_height
@internal_height+=_button.height
end
return _button
end
def input(text, x, y, width = Input::WIDTH, size = 18, color = Gosu::Color::BLACK, tooltip = "")
relative_x = @x+x
relative_y = @y+y
_input = Input.new(text, relative_x, relative_y, width, size, color)
@elements.push(_input)
if _input.y-(_input.height*2) > @internal_height
@internal_height+=_input.height
end
return _input
end
def check_box(x, y, checked = false, size = CheckBox::SIZE)
relative_x = @x+x
relative_y = @y+y
_check_box = CheckBox.new(relative_x, relative_y, checked, size)
@elements.push(_check_box)
if _check_box.y-(_check_box.height*2) > @internal_height
@internal_height+=_check_box.height
end
return _check_box
end
def resize
if @allow_recreation_on_resize
$window.active_container = self.class.new
end
end
# Fills container background with color
def fill(color = Gosu::Color::BLACK, z = 0)
$window.draw_rect(@x, @y, @width, @height, color, z)
end
def set_layout_y(start, spacing)
@layout_y_start = start
@layout_y_spacing = spacing
@layout_y_count = 0
end
def layout_y(stay = false)
i = @layout_y_start+(@layout_y_spacing*@layout_y_count)
@layout_y_count+=1 unless stay
return i
end
# Return X position relative to container
def relative_x(int)
int-self.x
end
# Return Y position relative to container
def relative_y(int)
int-self.y
end
def calc_percentage(positive, total)
begin
i = ((positive.to_f/total.to_f)*100.0).round(2)
if !i.nan?
return "#{i}%"
else
"N/A"
end
rescue ZeroDivisionError => e
puts e
return "N/A" # 0 / 0, safe to assume no actionable data
end
end
end
end

View File

@@ -0,0 +1,117 @@
module CyberarmEngine
class Input
WIDTH = 200
FOCUS_BACKGROUND_COLOR = Gosu::Color.rgb(150,150,144)
NO_FOCUS_BACKGROUND_COLOR = Gosu::Color.rgb(130,130,130)
attr_accessor :text, :x, :y, :width, :size, :color, :type, :focus
attr_reader :text_object, :text_input, :height, :fixed_x
def initialize(text, x, y, width = WIDTH, size = Text::SIZE, color = Gosu::Color::BLACK, tooltip = "", type = nil)
@text = text
@x, @y= x, y
@width= width
@size = size
@color= color
@tooltip=tooltip
@type = type
@focus = false
@text_object = Text.new(text, x: x, y: y, size: size, color: color, shadow: true)
@height = @text_object.height
@text_input = Gosu::TextInput.new
@text_input.text = @text
@background_color = NO_FOCUS_BACKGROUND_COLOR
@fixed_x = @x
@x_offset= 0
@carot_ticks = 0
@carot_width = 2.5
@carot_height= @text_object.height
@carot_color = Gosu::Color.rgb(50,50,25)
@carot_show_ticks = 25
@show_carot = true
return self
end
def text=(string)
@text = string
@text_input.text, @text_object.text = @text, @text
end
def draw
$window.draw_rect(x, y, width, height, Gosu::Color::BLACK)
$window.draw_rect(x+1, y+1, width-2, height-2, @background_color)
Gosu.clip_to(x, @text_object.y, width, @text_object.height) do
@text_object.draw
# Carot (Cursor)
$window.draw_rect((@x+@text_object.width)-@x_offset, @text_object.y, @carot_width, @carot_height, @carot_color) if @show_carot && @focus
end
end
def update
@text_object.y = @y+BUTTON_PADDING
if (@text_object.width+@carot_width)-@width >= 0
@x_offset = (@text_object.width+@carot_width)-@width
else
@x_offset = 0
end
@text = @text_object.text
@carot_ticks+=1
if @carot_ticks >= @carot_show_ticks
if @show_carot
@show_carot = false
else
@show_carot = true
end
@carot_ticks = 0
end
if @focus
@text_object.text = @text_input.text
$window.text_input = @text_input unless $window.text_input == @text_input
end
if mouse_over? && $window.button_down?(Gosu::MsLeft)
@focus = true
@background_color = FOCUS_BACKGROUND_COLOR
end
if !mouse_over? && $window.button_down?(Gosu::MsLeft)
@focus = false
$window.text_input = nil
@background_color = NO_FOCUS_BACKGROUND_COLOR
end
if @text_object.width >= @width
@text_object.x = self.fixed_x-@x_offset
else
@text_object.x = self.fixed_x
end
end
def mouse_over?
if $window.mouse_x.between?(@x, @x+width)
if $window.mouse_y.between?(@y, @y+height)
true
end
end
end
def width(text_object = @text_object)
# text_object.textobject.text_width(text_object.text)+BUTTON_PADDING*2
@width
end
def height(text_object = @text_object)
text_object.textobject.height+BUTTON_PADDING*2
end
end
end

View File

@@ -0,0 +1,3 @@
module CyberarmEngine
VERSION = "0.1.0"
end