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
## A number consumer that will create numbers when an extractor is placed on it.
require './dialouge_box.rb'
CONSUMER_DEBUG = false
BORDER = 2
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
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)) {
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
# Consumes numbers created
@@ -26,11 +37,20 @@ class Consumer
# @param camera_x [Integer] The camera X position
# @param camera_y [Integer] The camera Y position
# @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_y = (((((@screen_height / @box_size.to_f) / 2.0) + (@y - camera_y) * camera_zoom) * @box_size) + BORDER * 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
# 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}"
end
@image.draw(@draw_x, @draw_y, 0, @camera_zoom, @camera_zoom)
@tooltip.draw()
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 './consumer.rb'
require './dialouge_box.rb'
FONT_PATH = 'assets/font/Cousine-Regular.ttf'
# Viewport resolution
WIDTH = 1920
HEIGHT = 1080
WIDTH = Gosu::screen_width
HEIGHT = Gosu::screen_height
BOX_SIZE = 64
# Default game settings
@@ -24,7 +27,7 @@ GAME_PRODUCER_BASE_SPEED = 1
# Camera settings
CAMERA_MOVE_RANGE = 10
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_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_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
begin
game_save_data = YAML.load_file("#{GAME_SAVE_DIRECTORY}/positions.yaml")
@@ -92,61 +98,6 @@ class NumFactory < Gosu::Window
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
# Move the camera to the center of the map:
@@ -219,15 +170,15 @@ class NumFactory < Gosu::Window
### CAMERA ###
# Move the camera if needed
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
@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
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
@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
# Prevent camera from leaving the screen
@@ -238,7 +189,7 @@ class NumFactory < Gosu::Window
### ITEMS ###
@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
@belts.each do |belt|
@@ -246,8 +197,12 @@ class NumFactory < Gosu::Window
end
@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
@dialouges.each do |dialouge|
dialouge.update(0, 0, newtext: "My new text is: #{delta_mult}")
end
end
## Called when OS wants to update window.
@@ -280,15 +235,20 @@ class NumFactory < Gosu::Window
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)
Gosu::Image.from_text("Tick time: #{((Time.now() - @tick_time).to_f * 1000).to_i}", 20).draw(1600, 25, 1)
Gosu::Image.from_text("FPS: #{Gosu.fps}", 20).draw(1600, 50, 1)
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("Camera location: #{@camera_x}, #{@camera_y}", 20).draw(1600, 200, 1)
Gosu::Image.from_text("Camera zoom: #{@camera_zoom}, #{@camera_x_zoom_offset}", 20).draw(1600, 225, 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)
@dialouges.each do |dialouge|
dialouge.draw()
end
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("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("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
+19 -4
View File
@@ -1,8 +1,12 @@
## Nathan Hinton
## A number producer that will create numbers when an extractor is placed on it.
require './dialouge_box.rb'
PRODUCER_DEBUG = false
BORDER = 2
HOVER_TIME = 500 # ms
class Producer
attr_reader :draw_x, :draw_y
@@ -15,16 +19,17 @@ class Producer
@x = x
@y = y
@number = [number, 1].max
@rate = (30/rate).to_i
@rate = rate
@box_size = box_size
@screen_width = screen_width
@screen_height = screen_height
@image = Gosu.render(@box_size - (2 * BORDER), @box_size - (2 * BORDER)) {
# Render the item
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
# 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_y [Integer] The camera Y position
# @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_y = (((((@screen_height / @box_size.to_f) / 2.0) + (@y - camera_y) * camera_zoom) * @box_size) + BORDER * 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
# 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}"
end
@image.draw(@draw_x, @draw_y, 0, @camera_zoom, @camera_zoom)
@tooltip.draw()
end
end