4 Commits

22 changed files with 414 additions and 83 deletions
+33
View File
@@ -1,3 +1,36 @@
# number_factory # number_factory
A game where you create combinations of numbers! A game where you create combinations of numbers!
# UI elements
If you hover over the producers you will see the speed at which it produces.
If you hover over the consumer, you can see your next goal or quest
## tools
### Extractor
Extracts numbers. It is a three by three square and populates numbers from any
side (max 12) every time the producer ticks.
### Conveyer belt
Can move numbers around.
### Adder
Can output to either side but will only output to one space. Prefers the slot
on the left. If it is full though it will use the slots to the right
### Multiplier
### Subtractor
### Divider
### Exponent
### Logarithm
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 653 B

After

Width:  |  Height:  |  Size: 754 B

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 832 B

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 550 B

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.
+7 -15
View File
@@ -14,11 +14,12 @@ TASKS = [
] ]
class Consumer class Consumer
attr_reader :draw_x, :draw_y attr_reader :draw_x, :draw_y, :size_x, :size_y
# Create consumer at a position with the number and rate specified # Create consumer at a position with the number and rate specified
# @param x [Integer] X position to start at # @param x [Integer] X position to start at
# @param y [Integer] Y position to start at # @param y [Integer] Y position to start at
def initialize(x, y, box_size, screen_width, screen_height) def initialize(parent, x, y, box_size, screen_width, screen_height)
@parent = parent
@x = x - SIZE / 2 @x = x - SIZE / 2
@y = y - SIZE / 2 @y = y - SIZE / 2
@box_size = box_size @box_size = box_size
@@ -28,8 +29,8 @@ class Consumer
Gosu.draw_rect(0, 0, (SIZE * @box_size) - (2 * BORDER), (SIZE * @box_size) - (2 * BORDER), Gosu::Color::GREEN, 0) Gosu.draw_rect(0, 0, (SIZE * @box_size) - (2 * BORDER), (SIZE * @box_size) - (2 * BORDER), Gosu::Color::GREEN, 0)
} }
@task_index = 0 @task_index = 0
@tooltip_timer = 0 @tooltip = @parent.register_dialouge(@x, @y, @box_size * SIZE, @box_size * SIZE, TASKS[@task_index], 500)
@tooltip = DialougeBox.new(@x, @y, WIDTH, HEIGHT, TASKS[@task_index]) @size_x = @size_y = 3
end end
# Consumes numbers created # Consumes numbers created
@@ -41,16 +42,8 @@ class Consumer
@draw_x = (((((@screen_width / @box_size.to_f) / 2.0) + (@x - camera_x) * camera_zoom) * @box_size) + BORDER * camera_zoom) @draw_x = (((((@screen_width / @box_size.to_f) / 2.0) + (@x - camera_x) * camera_zoom) * @box_size) + BORDER * camera_zoom)
@draw_y = (((((@screen_height / @box_size.to_f) / 2.0) + (@y - camera_y) * camera_zoom) * @box_size) + BORDER * camera_zoom) @draw_y = (((((@screen_height / @box_size.to_f) / 2.0) + (@y - camera_y) * camera_zoom) * @box_size) + BORDER * camera_zoom)
@camera_zoom = camera_zoom @camera_zoom = camera_zoom
if 0 < mouse_x - @draw_x && mouse_x - @draw_x < (SIZE * @box_size * @camera_zoom) && 0 < mouse_y - @draw_y && mouse_y - @draw_y < (SIZE * @box_size * @camera_zoom)
@tooltip_timer += 60.0 * delta_mult @tooltip.move(@draw_x, @draw_y)
if @tooltip_timer > HOVER_TIME
@tooltip.show = true
@tooltip.update(@draw_x, @draw_y, @camera_zoom)
end
else
@tooltip_timer = 0
@tooltip.show = false
end
end end
# Draw the consumer. Uses the camera x and y to shift where it should draw # Draw the consumer. Uses the camera x and y to shift where it should draw
@@ -59,6 +52,5 @@ class Consumer
puts "Drawing at #{@x - camera_x}, #{@y - camera_y}" puts "Drawing at #{@x - camera_x}, #{@y - camera_y}"
end end
@image.draw(@draw_x, @draw_y, 0, @camera_zoom, @camera_zoom) @image.draw(@draw_x, @draw_y, 0, @camera_zoom, @camera_zoom)
@tooltip.draw()
end end
end end
+40 -26
View File
@@ -3,18 +3,26 @@
TEXT_SIZE = 20 TEXT_SIZE = 20
TEXT_MARGIN = 3 TEXT_MARGIN = 3
class DialougeBox class DialougeBox
attr_accessor :show # @param draw_x [Integer]
def initialize(parent_x, parent_y, screen_width, screen_height, text) # @param draw_y [Integer]
# @param size_x [Integer] The width that this should open at (in pixels at zero zoom)
# @param size_y [Integer] The height that this should open at (in pixels at zero zoom)
def initialize(x, y, size_x, size_y, screen_width, screen_height, text, box_size, hover_time)
@text = text @text = text
@longest_line = ((@text.split("\n").map { |ss| ss.length}.max) / 2.25).to_i @longest_line = ((@text.split("\n").map { |ss| ss.length}.max) / 2.25).to_i
@line_count = @text.split("\n").length @line_count = @text.split("\n").length
@x = parent_x @x = x
@y = parent_y @y = y
@show = false @size_x = size_x
@size_y = size_y
@screen_width = screen_width @screen_width = screen_width
@screen_height = screen_height @screen_height = screen_height
@box_size = box_size
@hover_time = hover_time
@show = false
@image = Gosu.render(((TEXT_MARGIN * 2) + TEXT_SIZE) * @longest_line, (TEXT_SIZE + TEXT_MARGIN) * @line_count) { @image = Gosu.render(((TEXT_MARGIN * 2) + TEXT_SIZE) * @longest_line, (TEXT_SIZE + TEXT_MARGIN) * @line_count) {
Gosu.draw_rect( Gosu.draw_rect(
0, 0,
@@ -26,34 +34,40 @@ class DialougeBox
) )
Gosu::Image.from_text(text, TEXT_SIZE, font: FONT_PATH).draw(TEXT_MARGIN, TEXT_MARGIN) Gosu::Image.from_text(text, TEXT_SIZE, font: FONT_PATH).draw(TEXT_MARGIN, TEXT_MARGIN)
} }
@timer = 0
@draw_x = 0
@draw_y = 0
end end
def update(x, y, camera_zoom, newtext: nil) # Used to move the dialouge box around
if !newtext.nil? # @param x [Integer] The x position to move to.
@text = newtext # @param y [Integer] The y position to move to.
@longest_line = ((@text.split("\n").map { |ss| ss.length}.max) / 3.5).to_i def move(x, y)
@line_count = @text.split("\n").length @draw_x = x
@draw_y = y
@image = Gosu.render(((TEXT_MARGIN * 2) + TEXT_SIZE) * @longest_line, (TEXT_SIZE + TEXT_MARGIN) * @line_count) { end
Gosu.draw_rect(
0, # Update called every delta time
0, def update(delta_mult, camera_zoom, mouse_x, mouse_y)
(((TEXT_MARGIN * 2) + TEXT_SIZE) * @longest_line) + @x,
((TEXT_SIZE + TEXT_MARGIN) * @line_count) + @y,
Gosu::Color.new(0xC0, 0xFF, 0xFF, 0xFF),
0,
)
Gosu::Image.from_text(newtext, TEXT_SIZE, font: FONT_PATH).draw(TEXT_MARGIN, TEXT_MARGIN)
}
end
@camera_zoom = camera_zoom @camera_zoom = camera_zoom
@x = x
@y = y if 0 < mouse_x - @draw_x && mouse_x - @draw_x < (@size_x * @camera_zoom) && 0 < mouse_y - @draw_y && mouse_y - @draw_y < (@size_y * @camera_zoom)
@timer += 60.0 * delta_mult
if @timer > @hover_time
@show = true
end
else
@timer = 0
@show = false
end
end end
## Draw the dialouge if it is supposed to be shown.
def draw() def draw()
if @show if @show
@image.draw(@x, @y, 0, @camera_zoom, @camera_zoom) @image.draw(@draw_x, @draw_y, 0, @camera_zoom, @camera_zoom)
end end
end end
end end
+28
View File
@@ -0,0 +1,28 @@
# Nathan Hinton
#
# When placed it will extract numbers at a specified rate and place them on any
# conveyer belts that are adjacent to it.
class Extractor
attr_reader :draw_x, :draw_y, :size_x, :size_y
def initialize(x, y, box_size)
@size_x = @size_y = 3
@x = x - @size_x / 2
@y = y - @size_y / 2
@box_size = box_size
@image = Gosu.render((@size_x * @box_size) - (2 * BORDER), (@size_y * @box_size) - (2 * BORDER)) {
Gosu::Image.new('assets/images/extractor.png').draw(0, 0, 0, @box_size / 32.0, @box_size / 32.0)
Gosu::Image.from_text("#{@number}", 20, font: FONT_PATH).draw(10 / 32.0 * @box_size, (8 / 32.0 * @box_size), 1, 2, 2, 0xFFFA32C0)
}
end
def update(delta_mult, camera_x, camera_y, camera_zoom)
@draw_x = (((((WIDTH / @box_size.to_f) / 2.0) + (@x - camera_x) * camera_zoom) * @box_size) + BORDER * camera_zoom)
@draw_y = (((((HEIGHT / @box_size.to_f) / 2.0) + (@y - camera_y) * camera_zoom) * @box_size) + BORDER * camera_zoom)
@camera_zoom = camera_zoom
end
def draw()
@image.draw(@draw_x, @draw_y, 0, @camera_zoom, @camera_zoom)
end
end
+71
View File
@@ -0,0 +1,71 @@
# Nathan Hinton
# Holds a grid of each otem in the game
class GameGrid
def initialize(game_width, game_height)
@game_grid = []
game_width.times do |xx|
@game_grid.append(Array.new(game_height))
end
end
## Add an item to the grid
# @param x [Integer] The x position (top left corner of item)
# @param y [Integer] The y position (top left corner of item)
# @param item [Object] The item to add. Should be an actual reference to the item
# @retval [Boolean] True if the item was placed, false otherwise (space conflict)
def add_item(x, y, item)
size_x = item.size_x
size_y = item.size_y
puts "#{item.to_s}"
puts "top left: (#{x}, #{y}), size: (#{size_x}, #{size_y})"
# Check that the grid is empty in those spots:
size_x.times do |xx|
size_y.times do |yy|
unless @game_grid[x + xx][y + yy].nil?
puts "Failed to add item: #{item.to_s}:"
puts " - top left: (#{x}, #{y}), size: (#{size_x}, #{size_y}), collision: (#{xx}, #{yy})"
return false
end
end
end
# place item in grid
size_x.times do |xx|
size_y.times do |yy|
@game_grid[x + xx][y + yy] = item
end
end
return true
end
## Add an item to the grid
# @param x [Integer] The x position (top left corner of item)
# @param y [Integer] The y position (top left corner of item)
# @param item [Object] The item to remove. Used to ensure we are removing the right thing.
def remove_item(x, y, item)
size_x = item.size_x
size_y = item.size_y
# Check that the grid is empty in those spots:
size_x.times do |xx|
size_y.times do |yy|
if @game_grid[x + xx][y + yy] != item
raise RuntimeError.new('Item mismatch in internal game grid! Game state corrupted1')
end
end
end
# place item in grid
size_x.times do |xx|
size_y.times do |yy|
@game_grid[x + xx][y + yy] = nil
end
end
end
end
+144 -21
View File
@@ -5,9 +5,12 @@
require 'gosu' require 'gosu'
require 'yaml' require 'yaml'
require './gamegrid.rb'
require './extractor.rb'
require './producer.rb' require './producer.rb'
require './consumer.rb' require './consumer.rb'
require './dialouge_box.rb' require './dialouge_box.rb'
require './ui.rb'
FONT_PATH = 'assets/font/Cousine-Regular.ttf' FONT_PATH = 'assets/font/Cousine-Regular.ttf'
@@ -18,8 +21,8 @@ BOX_SIZE = 64
# Default game settings # Default game settings
GAME_SAVE_DIRECTORY = 'game_save_data' GAME_SAVE_DIRECTORY = 'game_save_data'
GAME_WIDTH = 101 # Odd numbers look best, in squares GAME_WIDTH = 201 # Odd numbers look best, in squares
GAME_HEIGHT = 101 GAME_HEIGHT = 201
GAME_PRODUCER_CHANCE = 0.01 GAME_PRODUCER_CHANCE = 0.01
GAME_PRODUCER_VALUE_MULT = 0.1 GAME_PRODUCER_VALUE_MULT = 0.1
GAME_PRODUCER_BASE_SPEED = 1 GAME_PRODUCER_BASE_SPEED = 1
@@ -32,11 +35,16 @@ CAMERA_MIN_ZOOM = 16 # Boxes across
CAMERA_MAX_ZOOM = 80 # Boxes across CAMERA_MAX_ZOOM = 80 # Boxes across
class NumFactory < Gosu::Window class NumFactory < Gosu::Window
attr_accessor :current_tool
def initialize def initialize
super WIDTH, HEIGHT, :fullscreen => true super WIDTH, HEIGHT, :fullscreen => true
self.caption = "Number factory" self.caption = "Number factory"
@background_color = Gosu::Color::BLUE @background_color = Gosu::Color::BLUE
@cursor_image = Gosu::Image.new('assets/images/cursor.png')
@cursor = @cursor_image
@cursor_offset = 16
@camera_x = 0 @camera_x = 0
@camera_y = 0 @camera_y = 0
@@ -45,9 +53,19 @@ class NumFactory < Gosu::Window
@camera_x_zoom_offset = WIDTH.to_f / (@camera_boxes * BOX_SIZE * 2).to_f @camera_x_zoom_offset = WIDTH.to_f / (@camera_boxes * BOX_SIZE * 2).to_f
@camera_y_zoom_offset = HEIGHT.to_f / (@camera_boxes * BOX_SIZE * 2).to_f @camera_y_zoom_offset = HEIGHT.to_f / (@camera_boxes * BOX_SIZE * 2).to_f
@dd = DialougeBox.new(0, 0, WIDTH, HEIGHT, "This is a really really really really really really really really really really string\nof test text!") @ui = UI.new(self, WIDTH, HEIGHT)
@current_tool = nil
@extractor_image = Gosu::Image.new('assets/images/extractor.png')
@belt_image = Gosu::Image.new('assets/images/belt.png')
@adder_image = Gosu::Image.new('assets/images/adder.png')
@delete_image = Gosu::Image.new('assets/images/delete.png')
@dialouges = [] @dialouges = []
@extractors = []
# Setup the game grid
@game_grid = GameGrid.new(GAME_WIDTH, GAME_HEIGHT)
# Load from file or initialize a new game # Load from file or initialize a new game
begin begin
game_save_data = YAML.load_file("#{GAME_SAVE_DIRECTORY}/positions.yaml") game_save_data = YAML.load_file("#{GAME_SAVE_DIRECTORY}/positions.yaml")
@@ -74,18 +92,20 @@ class NumFactory < Gosu::Window
# Loop through and place producers # Loop through and place producers
center_x = ((@game_width - 1) / 2).to_i center_x = ((@game_width - 1) / 2).to_i
center_y = ((@game_height - 1) / 2).to_i center_y = ((@game_height - 1) / 2).to_i
@consumers.append(
Consumer.new(center_x, center_y, BOX_SIZE, WIDTH, HEIGHT),
)
consumer = Consumer.new(self, center_x, center_y, BOX_SIZE, WIDTH, HEIGHT)
if @game_grid.add_item(center_x, center_y, consumer)
@consumers.append(consumer)
end
# The value of the producer is proportional to the distance from the center # The value of the producer is proportional to the distance from the center
((@game_width).to_i).times do |xx| ((@game_width).to_i).times do |xx|
(@game_height).to_i.times do |yy| (@game_height).to_i.times do |yy|
if rand < GAME_PRODUCER_CHANCE if rand < GAME_PRODUCER_CHANCE
# Place a producer: # Place a producer:
@producers.append( producer =
Producer.new( Producer.new(
self,
xx, xx,
yy, yy,
(Math.sqrt((xx - center_x)**2 + (yy - center_y) ** 2) * GAME_PRODUCER_VALUE_MULT).to_i, (Math.sqrt((xx - center_x)**2 + (yy - center_y) ** 2) * GAME_PRODUCER_VALUE_MULT).to_i,
@@ -94,7 +114,10 @@ class NumFactory < Gosu::Window
WIDTH, WIDTH,
HEIGHT, HEIGHT,
) )
) # Add an item to the game with checking that the internal game state is good
if @game_grid.add_item(xx, yy, producer)
@producers.append(producer)
end
end end
end end
end end
@@ -121,8 +144,44 @@ class NumFactory < Gosu::Window
end end
# Disable cursor in the window
def needs_cursor?
false
end
def button_down(id) def button_down(id)
### Process mouse ###
mouse_used = @ui.update(self.mouse_x, self.mouse_y)
# They clicked in the game screen, attempt to place an item
if !mouse_used && id == Gosu::MS_LEFT
case @current_tool
when 'delete'
@cursor = @delete_image
@cursor_offset = @delete_image.height
#break
when 'belt'
@cursor = @belt_image
@cursor_offset = @belt_image.height
#break
when 'adder'
@cursor = @adder_image
@cursor_offset = @adder_image.height
#break
when 'extractor'
#xx = @camera_x + ((((self.mouse_x) - (WIDTH/2)) / BOX_SIZE - 1) * @camera_zoom).to_i
#yy = @camera_y + ((((self.mouse_y) - (HEIGHT/2)) / BOX_SIZE - 1) * @camera_zoom).to_i
xx = @camera_x + ((self.mouse_x - @cursor_offset + (BOX_SIZE * @camera_zoom)) / (BOX_SIZE * @camera_zoom)).to_i
yy = @camera_y + ((self.mouse_y - @cursor_offset + (BOX_SIZE * @camera_zoom)) / (BOX_SIZE * @camera_zoom))
extractor = Extractor.new(xx, yy, BOX_SIZE)
if @game_grid.add_item(xx, yy, extractor)
@extractors.append(extractor)
end
#break
end
end
### Process keyboard ###
if id == Gosu::KB_ESCAPE if id == Gosu::KB_ESCAPE
close close
elsif [Gosu::MS_WHEEL_UP, Gosu::KB_Z].include? id elsif [Gosu::MS_WHEEL_UP, Gosu::KB_Z].include? id
@@ -154,12 +213,34 @@ class NumFactory < Gosu::Window
@camera_zoom = WIDTH.to_f / (@camera_boxes * BOX_SIZE).to_f @camera_zoom = WIDTH.to_f / (@camera_boxes * BOX_SIZE).to_f
@camera_x_zoom_offset = WIDTH.to_f / (@camera_boxes * BOX_SIZE * 2).to_f @camera_x_zoom_offset = WIDTH.to_f / (@camera_boxes * BOX_SIZE * 2).to_f
@camera_y_zoom_offset = HEIGHT.to_f / (@camera_boxes * BOX_SIZE * 2).to_f @camera_y_zoom_offset = HEIGHT.to_f / (@camera_boxes * BOX_SIZE * 2).to_f
elsif id == Gosu::KB_G
@cursor = @cursor_image
@cursor_offset = 16
@current_tool = nil
else else
super super
end end
end end
## Register a dialouge into the game
# @param x [Integer] The x position that the dialouge should be drawn at.
# @param y [Integer] The y position that the dialouge should be drawn at.
# @param size_x [Integer] The pixel width
# @param size_y [Integer] The pixel width
# @param text [String] The text for the dialouge box
def register_dialouge(x, y, size_x, size_y, text, popup_time)
dialouge = DialougeBox.new(x, y, size_x, size_y, WIDTH, HEIGHT, text, BOX_SIZE, popup_time)
@dialouges.append(dialouge)
return dialouge
end
## Remove a dialouge from the game
# @param dialouge [DialougeBox] The dialouge to remove
def deregister_dialouge(dialouge)
@dialouges.delete(dialouge)
end
## Called every frame ## Called every frame
def update def update
@delta_time = Time.now() - @tick_time @delta_time = Time.now() - @tick_time
@@ -182,36 +263,58 @@ class NumFactory < Gosu::Window
end end
# Prevent camera from leaving the screen # Prevent camera from leaving the screen
@camera_x = [@camera_x, 0].max @camera_x = [@camera_x.to_i, 0].max
@camera_x = [@camera_x, @game_width].min @camera_x = [@camera_x.to_i, @game_width].min
@camera_y = [@camera_y, 0].max @camera_y = [@camera_y.to_i, 0].max
@camera_y = [@camera_y, @game_width].min @camera_y = [@camera_y.to_i, @game_width].min
### ITEMS ### ### ITEMS ###
@producers.each do |producer| @producers.each do |producer|
producer.update(delta_mult, @camera_x, @camera_y, @camera_zoom, self.mouse_x, self.mouse_y) producer.update(delta_mult, @camera_x, @camera_y, @camera_zoom)
end end
@belts.each do |belt| @extractors.each do |extractor|
belt.update(delta_mult) extractor.update(delta_mult, @camera_x, @camera_y, @camera_zoom)
end end
@consumers.each do |consumer| @consumers.each do |consumer|
consumer.update(delta_mult, @camera_x, @camera_y, @camera_zoom, self.mouse_x, self.mouse_y) consumer.update(delta_mult, @camera_x, @camera_y, @camera_zoom, self.mouse_x, self.mouse_y)
end end
# Finally process the dialouges
@dialouges.each do |dialouge| @dialouges.each do |dialouge|
dialouge.update(0, 0, newtext: "My new text is: #{delta_mult}") dialouge.update(delta_mult, @camera_zoom, self.mouse_x, self.mouse_y)
end
case @current_tool
when 'delete'
@cursor = @delete_image
@cursor_offset = @delete_image.height
#break
when 'belt'
@cursor = @belt_image
@cursor_offset = @belt_image.height
#break
when 'adder'
@cursor = @adder_image
@cursor_offset = @adder_image.height
#break
when 'extractor'
@cursor = @extractor_image
@cursor_offset = @extractor_image.height
#break
end end
end end
## Called when OS wants to update window. ## Called when OS wants to update window.
def draw def draw
# Draw mouse coords: # Draw mouse coords:
onscreen_items = 0 onscreen_items = 0
# TODO: The background does *not* actually need to move. It can just stay
# in one spot and scale... This would make the program load so much faster
# as well as allow for larger maps.
@background.draw( @background.draw(
(((((WIDTH / BOX_SIZE.to_f) / 2.0) - (@camera_x * @camera_zoom)) * (BOX_SIZE))), (((((WIDTH / BOX_SIZE.to_f) / 2.0) - (@camera_x * @camera_zoom)) * (BOX_SIZE))),
((((HEIGHT / BOX_SIZE.to_f) / 2.0) - (@camera_y * @camera_zoom)) * (BOX_SIZE)), ((((HEIGHT / BOX_SIZE.to_f) / 2.0) - (@camera_y * @camera_zoom)) * (BOX_SIZE)),
0, 0,
@camera_zoom, @camera_zoom,
@@ -226,6 +329,15 @@ class NumFactory < Gosu::Window
end end
end end
end end
@extractors.each do |extractor|
if extractor.draw_x <= WIDTH && extractor.draw_x >= 0
if extractor.draw_y <= HEIGHT && extractor.draw_y >= 0
extractor.draw()
onscreen_items += 1
end
end
end
@consumers.each do |consumer| @consumers.each do |consumer|
if consumer.draw_x <= WIDTH && consumer.draw_x >= 0 if consumer.draw_x <= WIDTH && consumer.draw_x >= 0
@@ -240,8 +352,12 @@ class NumFactory < Gosu::Window
dialouge.draw() dialouge.draw()
end end
@ui.draw()
Gosu::Image.from_text("#{width}, #{height}", 20, font: FONT_PATH).draw(1600, 0, 1) Gosu::Image.from_text("#{width}, #{height}", 20, font: FONT_PATH).draw(1600, 0, 1)
Gosu::Image.from_text("#{mouse_x}, #{mouse_y}", 20, font: FONT_PATH).draw(1600, 100, 1) Gosu::Image.from_text("#{mouse_x}, #{mouse_y}", 20, font: FONT_PATH).draw(1600, 100, 1)
Gosu::Image.from_text("#{@camera_x + ((self.mouse_x - @cursor_offset + (BOX_SIZE * @camera_zoom)) / (BOX_SIZE * @camera_zoom)).to_i}, #{@camera_y + ((self.mouse_y - (HEIGHT/2)) / BOX_SIZE * @camera_zoom).to_i}", 20, font: FONT_PATH).draw(1600, 125, 1)
Gosu::Image.from_text("Tick time: #{((Time.now() - @tick_time).to_f * 1000).to_i}", 20, font: FONT_PATH).draw(1600, 25, 1) Gosu::Image.from_text("Tick time: #{((Time.now() - @tick_time).to_f * 1000).to_i}", 20, font: FONT_PATH).draw(1600, 25, 1)
Gosu::Image.from_text("FPS: #{Gosu.fps}", 20, font: FONT_PATH).draw(1600, 50, 1) Gosu::Image.from_text("FPS: #{Gosu.fps}", 20, font: FONT_PATH).draw(1600, 50, 1)
Gosu::Image.from_text("items on screen: #{onscreen_items}", 20, font: FONT_PATH).draw(1600, 75, 1) Gosu::Image.from_text("items on screen: #{onscreen_items}", 20, font: FONT_PATH).draw(1600, 75, 1)
@@ -249,6 +365,13 @@ class NumFactory < Gosu::Window
Gosu::Image.from_text("Camera location: #{@camera_x}, #{@camera_y}", 20, font: FONT_PATH).draw(1600, 200, 1) Gosu::Image.from_text("Camera location: #{@camera_x}, #{@camera_y}", 20, font: FONT_PATH).draw(1600, 200, 1)
Gosu::Image.from_text("Camera zoom: #{@camera_zoom}, #{@camera_x_zoom_offset}", 20, font: FONT_PATH).draw(1600, 225, 1) Gosu::Image.from_text("Camera zoom: #{@camera_zoom}, #{@camera_x_zoom_offset}", 20, font: FONT_PATH).draw(1600, 225, 1)
Gosu::Image.from_text("Camera viewport: (#{@camera_min_x}, #{@camera_min_y}) to (#{@camera_max_x}, #{@camera_max_y})", 20, font: FONT_PATH).draw(1600, 250, 1) Gosu::Image.from_text("Camera viewport: (#{@camera_min_x}, #{@camera_min_y}) to (#{@camera_max_x}, #{@camera_max_y})", 20, font: FONT_PATH).draw(1600, 250, 1)
if @cursor == @cursor_image
@cursor.draw(self.mouse_x - @cursor_offset, self.mouse_y - @cursor_offset, 10)
else
@cursor.draw(self.mouse_x - @cursor_offset, self.mouse_y - @cursor_offset, 10, BOX_SIZE / 32.0 * @camera_zoom, BOX_SIZE / 32.0 * @camera_zoom, 0x88_888888)
end
Gosu.draw_rect(self.mouse_x - 2, self.mouse_y - 2, 4, 4, Gosu::Color::RED)
end end
end end
+12 -21
View File
@@ -1,23 +1,20 @@
## Nathan Hinton ## Nathan Hinton
## A number producer that will create numbers when an extractor is placed on it. ## A number producer that will create numbers when an extractor is placed on it.
require './dialouge_box.rb'
PRODUCER_DEBUG = false PRODUCER_DEBUG = false
BORDER = 2 BORDER = 2
HOVER_TIME = 500 # ms
class Producer class Producer
attr_reader :draw_x, :draw_y attr_reader :draw_x, :draw_y, :size_x, :size_y
# Create producer at a position with the number and rate specified # Create producer at a position with the number and rate specified
# @param x [Integer] X position to start at # @param x [Integer] X position to start at
# @param y [Integer] Y position to start at # @param y [Integer] Y position to start at
# @param number [Integer] The number to produce # @param number [Integer] The number to produce
# @param rate [Integer] The speed in numbers per second to produce # @param rate [Integer] The speed in numbers per second to produce
def initialize(x, y, number, rate, box_size, screen_width, screen_height) def initialize(parent, x, y, number, rate, box_size, screen_width, screen_height)
@x = x @x = x
@y = y @y = y
@parent = parent
@number = [number, 1].max @number = [number, 1].max
@rate = rate @rate = rate
@box_size = box_size @box_size = box_size
@@ -25,12 +22,15 @@ class Producer
@screen_height = screen_height @screen_height = screen_height
@image = Gosu.render(@box_size - (2 * BORDER), @box_size - (2 * BORDER)) { @image = Gosu.render(@box_size - (2 * BORDER), @box_size - (2 * BORDER)) {
# Render the item # Render the item
Gosu.draw_rect(0, 0, @box_size - (2 * BORDER), @box_size - (2 * BORDER), Gosu::Color::RED, 0) Gosu::Image.new('assets/images/producer.png').draw(0, 0, 0, @box_size / 32.0, @box_size / 32.0)
Gosu::Image.from_text("#{@number}", 20, font: FONT_PATH).draw(5, 5, 1) Gosu::Image.from_text("#{@number}", 20, font: FONT_PATH).draw(10 / 32.0 * @box_size, (8 / 32.0 * @box_size), 1, 2, 2, 0xFFFA32C0)
} }
@tooltip = DialougeBox.new(@x, @y, WIDTH, HEIGHT, "Produces #{@rate} number per second") puts "X: #{@x}, Y: #{@y}"
@tooltip = @parent.register_dialouge(@x, @y, @box_size, @box_size, "Produces #{@rate} number per second", 500)
@size_x = @size_y = 1
end end
# Creates numbers depending on the rate. This is done with knowing that the # Creates numbers depending on the rate. This is done with knowing that the
# game is 30 fps so we use that for a counter # game is 30 fps so we use that for a counter
@@ -39,20 +39,12 @@ class Producer
# @param camera_x [Integer] The camera X position # @param camera_x [Integer] The camera X position
# @param camera_y [Integer] The camera Y position # @param camera_y [Integer] The camera Y position
# @param camera_zoom [Float] The camera zoom # @param camera_zoom [Float] The camera zoom
def update(delta_mult, camera_x, camera_y, camera_zoom, mouse_x, mouse_y) def update(delta_mult, camera_x, camera_y, camera_zoom)
@draw_x = (((((@screen_width / @box_size.to_f) / 2.0) + (@x - camera_x) * camera_zoom) * @box_size) + BORDER * camera_zoom) @draw_x = (((((@screen_width / @box_size.to_f) / 2.0) + (@x - camera_x) * camera_zoom) * @box_size) + BORDER * camera_zoom)
@draw_y = (((((@screen_height / @box_size.to_f) / 2.0) + (@y - camera_y) * camera_zoom) * @box_size) + BORDER * camera_zoom) @draw_y = (((((@screen_height / @box_size.to_f) / 2.0) + (@y - camera_y) * camera_zoom) * @box_size) + BORDER * camera_zoom)
@camera_zoom = camera_zoom @camera_zoom = camera_zoom
if 0 < mouse_x - @draw_x && mouse_x - @draw_x < (@box_size * @camera_zoom) && 0 < mouse_y - @draw_y && mouse_y - @draw_y < (@box_size * @camera_zoom)
@tooltip_timer += 60.0 * delta_mult @tooltip.move(@draw_x, @draw_y)
if @tooltip_timer > HOVER_TIME
@tooltip.show = true
@tooltip.update(@draw_x, @draw_y, @camera_zoom)
end
else
@tooltip_timer = 0
@tooltip.show = false
end
end end
# Draw the producer. Uses the camera x and y to shift where it should draw # Draw the producer. Uses the camera x and y to shift where it should draw
@@ -61,6 +53,5 @@ class Producer
puts "Drawing at #{@x - camera_x}, #{@y - camera_y}" puts "Drawing at #{@x - camera_x}, #{@y - camera_y}"
end end
@image.draw(@draw_x, @draw_y, 0, @camera_zoom, @camera_zoom) @image.draw(@draw_x, @draw_y, 0, @camera_zoom, @camera_zoom)
@tooltip.draw()
end end
end end
+79
View File
@@ -0,0 +1,79 @@
# Nathan Hinton
# This is the UI for the game and will contain all of the sub elements required.
# There will be three main areas that we will be in charge of. First, the
# bottom bar has the selector of item types. There will be a menu in the top
# right as well as any store things that we need/
class UI
# Setup for the UI
# @param width [Integer] Width of screen in pixels
# @param height [Integer] Height of the screen in pixels
def initialize(parent, width, height)
@parent = parent
@width = width
@height = height
@tool_selector = []
@toolbar_width = width / 2
@toolbar_height = height / 9
@tool_info = [
['extractor', 96],
['belt', 32],
['adder', 64],
['delete', 32],
]
@tool_selector_image = Gosu.render(@toolbar_width, @toolbar_height) {
Gosu.draw_rect(
0,
0,
@toolbar_width,
@toolbar_height,
Gosu::Color.new(0xC0, 0xFF, 0xFF, 0xFF),
0)
# Loop through the tools:
@tool_info.each_with_index do |path, idx|
Gosu::Image.new("assets/images/#{path[0]}.png").draw(
idx * (@toolbar_height + 2),
2,
0,
(@toolbar_height / path[1].to_f),
(@toolbar_height / path[1].to_f),
)
end
}
@x = (@width / 2) - (@toolbar_width / 2)
@y = @height - @toolbar_height
@mouse_down_last_update = false
end
def update(mouse_x, mouse_y)
managed = false
# Only check if we are clicking
if Gosu.button_down?(Gosu::MS_LEFT)
if !@mouse_down_last_update
puts 'mouse clicked'
@mouse_down_last_update = true
# Check if we are in the right y area:
if mouse_y > @y
# Check if we are within the right zone
mouse_x_inset = mouse_x - @x
if 0 < mouse_x_inset && mouse_x_inset < @toolbar_width
managed = true
item_index = mouse_x_inset / (@toolbar_height + 2)
if item_index < @tool_info.length
@parent.current_tool = @tool_info[item_index][0]
puts "Selected item!"
end
end
end
end
else
@mouse_down_last_update = false
end
return managed
end
def draw()
@tool_selector_image.draw(@x, @y)
end
end