Compare commits

3 Commits

Author SHA1 Message Date
bionickatana 46d45783f3 Add dialouge boxes/tooltips (#10)
- [x] Update objects so they know when the mouse is on them
- [x] Remove testing code
- [x] Add into the producers
- [x] Add into the consumer
- [x] Standardize fonts

---------

Co-authored-by: leah <leah@hintonclan.org>
Reviewed-on: #10
2026-06-14 22:29:14 -06:00
bionickatana 693f5b83e9 Update main.rb (#8)
This works. I did find out in my testing that it might not set the zoom correct however as soon as you do zoom it works properly. Also odd aspect ratios (eg not my aspect ratio) cause the squares to be not so square

Reviewed-on: #8
Co-authored-by: nathan <nathan@hintonclan.org>
Co-committed-by: nathan <nathan@hintonclan.org>
2026-06-14 15:32:57 -06:00
bionickatana 8e7c0c9078 Fixed coordinate system and finally got zoom working (#1)
Reviewed-on: nathan/number_factory#1
Co-authored-by: bionickatana <nathan@hintonclan.org>
Co-committed-by: bionickatana <nathan@hintonclan.org>
2026-06-14 11:12:32 -06:00
5 changed files with 134 additions and 79 deletions
Binary file not shown.
+23 -2
View File
@@ -1,9 +1,17 @@
## Nathan Hinton ## Nathan Hinton
## A number consumer that will create numbers when an extractor is placed on it. ## A number consumer that will create numbers when an extractor is placed on it.
require './dialouge_box.rb'
CONSUMER_DEBUG = false CONSUMER_DEBUG = false
BORDER = 2 BORDER = 2
SIZE = 3 SIZE = 3
HOVER_TIME = 500 # ms
# This actually should be stored somewhere else. This is the goals/quests for the game
TASKS = [
"Collect 10 1's"
]
class Consumer class Consumer
attr_reader :draw_x, :draw_y attr_reader :draw_x, :draw_y
@@ -19,6 +27,9 @@ class Consumer
@image = Gosu.render((SIZE * @box_size) - (2 * BORDER), (SIZE * @box_size) - (2 * BORDER)) { @image = Gosu.render((SIZE * @box_size) - (2 * BORDER), (SIZE * @box_size) - (2 * BORDER)) {
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
@tooltip_timer = 0
@tooltip = DialougeBox.new(@x, @y, WIDTH, HEIGHT, TASKS[@task_index])
end end
# Consumes numbers created # Consumes numbers created
@@ -26,11 +37,20 @@ class Consumer
# @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) def update(delta_mult, camera_x, camera_y, camera_zoom, mouse_x, mouse_y)
@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
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
@@ -39,5 +59,6 @@ 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
+59
View File
@@ -0,0 +1,59 @@
# Nathan Hinotn
# Creates a simple dialouge box that can be spawned from any location
TEXT_SIZE = 20
TEXT_MARGIN = 3
class DialougeBox
attr_accessor :show
def initialize(parent_x, parent_y, screen_width, screen_height, text)
@text = text
@longest_line = ((@text.split("\n").map { |ss| ss.length}.max) / 2.25).to_i
@line_count = @text.split("\n").length
@x = parent_x
@y = parent_y
@show = false
@screen_width = screen_width
@screen_height = screen_height
@image = Gosu.render(((TEXT_MARGIN * 2) + TEXT_SIZE) * @longest_line, (TEXT_SIZE + TEXT_MARGIN) * @line_count) {
Gosu.draw_rect(
0,
0,
(((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(text, TEXT_SIZE, font: FONT_PATH).draw(TEXT_MARGIN, TEXT_MARGIN)
}
end
def update(x, y, camera_zoom, newtext: nil)
if !newtext.nil?
@text = newtext
@longest_line = ((@text.split("\n").map { |ss| ss.length}.max) / 3.5).to_i
@line_count = @text.split("\n").length
@image = Gosu.render(((TEXT_MARGIN * 2) + TEXT_SIZE) * @longest_line, (TEXT_SIZE + TEXT_MARGIN) * @line_count) {
Gosu.draw_rect(
0,
0,
(((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
@x = x
@y = y
end
def draw()
if @show
@image.draw(@x, @y, 0, @camera_zoom, @camera_zoom)
end
end
end
+33 -73
View File
@@ -7,10 +7,13 @@ require 'yaml'
require './producer.rb' require './producer.rb'
require './consumer.rb' require './consumer.rb'
require './dialouge_box.rb'
FONT_PATH = 'assets/font/Cousine-Regular.ttf'
# Viewport resolution # Viewport resolution
WIDTH = 1920 WIDTH = Gosu::screen_width
HEIGHT = 1080 HEIGHT = Gosu::screen_height
BOX_SIZE = 64 BOX_SIZE = 64
# Default game settings # Default game settings
@@ -24,7 +27,7 @@ GAME_PRODUCER_BASE_SPEED = 1
# Camera settings # Camera settings
CAMERA_MOVE_RANGE = 10 CAMERA_MOVE_RANGE = 10
CAMERA_MOVE_SPEED = 1 CAMERA_MOVE_SPEED = 1
CAMERA_MOVE_MAX_SPEED = 1 # (CAMERA_MOVE_RANGE * CAMERA_MOVE_SPEED / 3).to_i CAMERA_MOVE_MAX_SPEED = 5
CAMERA_MIN_ZOOM = 16 # Boxes across CAMERA_MIN_ZOOM = 16 # Boxes across
CAMERA_MAX_ZOOM = 80 # Boxes across CAMERA_MAX_ZOOM = 80 # Boxes across
@@ -42,6 +45,9 @@ 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!")
@dialouges = []
# 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")
@@ -92,61 +98,6 @@ class NumFactory < Gosu::Window
end end
end end
end end
@producers.append(
Producer.new(
0,
0,
(Math.sqrt((0 - center_x)**2 + (0 - center_y) ** 2) * GAME_PRODUCER_VALUE_MULT).to_i,
GAME_PRODUCER_BASE_SPEED,
BOX_SIZE,
WIDTH,
HEIGHT,
)
)
@producers.append(
Producer.new(
2,
2,
(Math.sqrt((2 - center_x)**2 + (2 - center_y) ** 2) * GAME_PRODUCER_VALUE_MULT).to_i,
GAME_PRODUCER_BASE_SPEED,
BOX_SIZE,
WIDTH,
HEIGHT,
)
)
@producers.append(
Producer.new(
2,
0,
(Math.sqrt((2 - center_x)**2 + (0 - center_y) ** 2) * GAME_PRODUCER_VALUE_MULT).to_i,
GAME_PRODUCER_BASE_SPEED,
BOX_SIZE,
WIDTH,
HEIGHT,
)
)
@producers.append(
Producer.new(
0,
2,
(Math.sqrt((0 - center_x)**2 + (2 - center_y) ** 2) * GAME_PRODUCER_VALUE_MULT).to_i,
GAME_PRODUCER_BASE_SPEED,
BOX_SIZE,
WIDTH,
HEIGHT,
)
)
@producers.append(
Producer.new(
10,
10,
1000,
GAME_PRODUCER_BASE_SPEED,
BOX_SIZE,
WIDTH,
HEIGHT,
)
)
end # End file loading end # End file loading
# Move the camera to the center of the map: # Move the camera to the center of the map:
@@ -219,15 +170,15 @@ class NumFactory < Gosu::Window
### CAMERA ### ### CAMERA ###
# Move the camera if needed # Move the camera if needed
if self.mouse_x < CAMERA_MOVE_RANGE if self.mouse_x < CAMERA_MOVE_RANGE
@camera_x -= 1#([(CAMERA_MOVE_SPEED * ((CAMERA_MOVE_RANGE - self.mouse_x ) / 2)).to_i, CAMERA_MOVE_MAX_SPEED].min * delta_mult) @camera_x -= ([(CAMERA_MOVE_SPEED * ((CAMERA_MOVE_RANGE - self.mouse_x ) / 5)), CAMERA_MOVE_MAX_SPEED].min * delta_mult)
elsif self.mouse_x > WIDTH - CAMERA_MOVE_RANGE elsif self.mouse_x > WIDTH - CAMERA_MOVE_RANGE
@camera_x += 1#([(CAMERA_MOVE_SPEED * ((CAMERA_MOVE_RANGE - (WIDTH - self.mouse_x) ) / 2)).to_i, CAMERA_MOVE_MAX_SPEED].min * delta_mult) @camera_x += ([(CAMERA_MOVE_SPEED * ((CAMERA_MOVE_RANGE - (WIDTH - self.mouse_x + 1)) / 5)), CAMERA_MOVE_MAX_SPEED].min * delta_mult)
end end
if self.mouse_y < CAMERA_MOVE_RANGE if self.mouse_y < CAMERA_MOVE_RANGE
@camera_y -= 1#([(CAMERA_MOVE_SPEED * ((CAMERA_MOVE_RANGE - self.mouse_y ) / 2)).to_i, CAMERA_MOVE_MAX_SPEED].min * delta_mult) @camera_y -= ([(CAMERA_MOVE_SPEED * ((CAMERA_MOVE_RANGE - self.mouse_y ) / 5)), CAMERA_MOVE_MAX_SPEED].min * delta_mult)
elsif self.mouse_y > HEIGHT - CAMERA_MOVE_RANGE elsif self.mouse_y > HEIGHT - CAMERA_MOVE_RANGE
@camera_y += 1#([(CAMERA_MOVE_SPEED * ((CAMERA_MOVE_RANGE - (HEIGHT - (self.mouse_y + 1)) ) / 2)).to_i, CAMERA_MOVE_MAX_SPEED].min * delta_mult) @camera_y += ([(CAMERA_MOVE_SPEED * ((CAMERA_MOVE_RANGE - (HEIGHT - (self.mouse_y + 1)) ) / 5)), CAMERA_MOVE_MAX_SPEED].min * delta_mult)
end end
# Prevent camera from leaving the screen # Prevent camera from leaving the screen
@@ -238,7 +189,7 @@ class NumFactory < Gosu::Window
### ITEMS ### ### ITEMS ###
@producers.each do |producer| @producers.each do |producer|
producer.update(delta_mult, @camera_x, @camera_y, @camera_zoom) producer.update(delta_mult, @camera_x, @camera_y, @camera_zoom, self.mouse_x, self.mouse_y)
end end
@belts.each do |belt| @belts.each do |belt|
@@ -246,8 +197,12 @@ class NumFactory < Gosu::Window
end end
@consumers.each do |consumer| @consumers.each do |consumer|
consumer.update(delta_mult, @camera_x, @camera_y, @camera_zoom) consumer.update(delta_mult, @camera_x, @camera_y, @camera_zoom, self.mouse_x, self.mouse_y)
end end
@dialouges.each do |dialouge|
dialouge.update(0, 0, newtext: "My new text is: #{delta_mult}")
end
end end
## Called when OS wants to update window. ## Called when OS wants to update window.
@@ -280,15 +235,20 @@ class NumFactory < Gosu::Window
end end
end end
end end
Gosu::Image.from_text("#{width}, #{height}", 20).draw(1600, 0, 1)
Gosu::Image.from_text("#{mouse_x}, #{mouse_y}", 20).draw(1600, 100, 1) @dialouges.each do |dialouge|
Gosu::Image.from_text("Tick time: #{((Time.now() - @tick_time).to_f * 1000).to_i}", 20).draw(1600, 25, 1) dialouge.draw()
Gosu::Image.from_text("FPS: #{Gosu.fps}", 20).draw(1600, 50, 1) end
Gosu::Image.from_text("items on screen: #{onscreen_items}", 20).draw(1600, 75, 1)
Gosu::Image.from_text("Camera boxes: #{@camera_boxes}", 20).draw(1600, 175, 1) Gosu::Image.from_text("#{width}, #{height}", 20, font: FONT_PATH).draw(1600, 0, 1)
Gosu::Image.from_text("Camera location: #{@camera_x}, #{@camera_y}", 20).draw(1600, 200, 1) Gosu::Image.from_text("#{mouse_x}, #{mouse_y}", 20, font: FONT_PATH).draw(1600, 100, 1)
Gosu::Image.from_text("Camera zoom: #{@camera_zoom}, #{@camera_x_zoom_offset}", 20).draw(1600, 225, 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("Camera viewport: (#{@camera_min_x}, #{@camera_min_y}) to (#{@camera_max_x}, #{@camera_max_y})", 20).draw(1600, 250, 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("Camera boxes: #{@camera_boxes}", 20, font: FONT_PATH).draw(1600, 175, 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 viewport: (#{@camera_min_x}, #{@camera_min_y}) to (#{@camera_max_x}, #{@camera_max_y})", 20, font: FONT_PATH).draw(1600, 250, 1)
end end
end end
+19 -4
View File
@@ -1,8 +1,12 @@
## 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
@@ -15,16 +19,17 @@ class Producer
@x = x @x = x
@y = y @y = y
@number = [number, 1].max @number = [number, 1].max
@rate = (30/rate).to_i @rate = rate
@box_size = box_size @box_size = box_size
@screen_width = screen_width @screen_width = screen_width
@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.draw_rect(0, 0, @box_size - (2 * BORDER), @box_size - (2 * BORDER), Gosu::Color::RED, 0)
Gosu::Image.from_text("#{@number}", 20).draw(5, 5, 1) Gosu::Image.from_text("#{@number}", 20, font: FONT_PATH).draw(5, 5, 1)
} }
@tooltip = DialougeBox.new(@x, @y, WIDTH, HEIGHT, "Produces #{@rate} number per second")
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
@@ -34,11 +39,20 @@ 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) def update(delta_mult, camera_x, camera_y, camera_zoom, mouse_x, mouse_y)
@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
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
@@ -47,5 +61,6 @@ 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