Finished allowing placement and collision detection. However, the placement is very inconsistent. Thinking about redoing coordinates again...

This commit is contained in:
2026-06-17 22:14:22 -06:00
parent 6f5ad9803f
commit e7825478f1
7 changed files with 161 additions and 36 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 434 B

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.
+3 -2
View File
@@ -14,7 +14,7 @@ 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
@@ -30,6 +30,7 @@ class Consumer
} }
@task_index = 0 @task_index = 0
@tooltip = @parent.register_dialouge(@x, @y, @box_size * SIZE, @box_size * SIZE, TASKS[@task_index], 500) @tooltip = @parent.register_dialouge(@x, @y, @box_size * SIZE, @box_size * SIZE, TASKS[@task_index], 500)
@size_x = @size_y = 3
end end
# Consumes numbers created # Consumes numbers created
@@ -37,7 +38,7 @@ 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, mouse_x, mouse_y, mouse_used) 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
+9 -7
View File
@@ -4,19 +4,21 @@
# conveyer belts that are adjacent to it. # conveyer belts that are adjacent to it.
class Extractor class Extractor
attr_reader :draw_x, :draw_y, :size_x, :size_y
def initialize(x, y, box_size) def initialize(x, y, box_size)
@x = x @size_x = @size_y = 3
@y = y @x = x - @size_x / 2
@y = y - @size_y / 2
@box_size = box_size @box_size = box_size
@image = Gosu.render(@box_size - (2 * BORDER), @box_size - (2 * BORDER)) { @image = Gosu.render((@size_x * @box_size) - (2 * BORDER), (@size_y * @box_size) - (2 * BORDER)) {
Gosu::Image.new('assets/images/producer.png').draw(0, 0, 0, @box_size / 32.0, @box_size / 32.0) 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) 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 end
def update(delta_mult, camera_x, camera_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 = (((((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 = (((((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
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
+73 -23
View File
@@ -5,6 +5,8 @@
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'
@@ -19,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
@@ -42,6 +44,7 @@ class NumFactory < Gosu::Window
@background_color = Gosu::Color::BLUE @background_color = Gosu::Color::BLUE
@cursor_image = Gosu::Image.new('assets/images/cursor.png') @cursor_image = Gosu::Image.new('assets/images/cursor.png')
@cursor = @cursor_image @cursor = @cursor_image
@cursor_offset = 16
@camera_x = 0 @camera_x = 0
@camera_y = 0 @camera_y = 0
@@ -57,9 +60,11 @@ class NumFactory < Gosu::Window
@adder_image = Gosu::Image.new('assets/images/adder.png') @adder_image = Gosu::Image.new('assets/images/adder.png')
@delete_image = Gosu::Image.new('assets/images/delete.png') @delete_image = Gosu::Image.new('assets/images/delete.png')
@dialouges = [ @dialouges = []
#DialougeBox.new(0, 5, BOX_SIZE, BOX_SIZE, WIDTH, HEIGHT, 'this is some really good test text!', BOX_SIZE, 500) @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
@@ -88,16 +93,17 @@ class NumFactory < Gosu::Window
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 = Consumer.new(self, center_x, center_y, BOX_SIZE, WIDTH, HEIGHT)
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, self,
xx, xx,
@@ -108,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
@@ -141,6 +150,38 @@ class NumFactory < Gosu::Window
end 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
@@ -174,6 +215,7 @@ class NumFactory < Gosu::Window
@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 elsif id == Gosu::KB_G
@cursor = @cursor_image @cursor = @cursor_image
@cursor_offset = 16
@current_tool = nil @current_tool = nil
else else
super super
@@ -221,31 +263,28 @@ 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 ###
mouse_used = @ui.update(self.mouse_x, self.mouse_y)
@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)
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, mouse_used) consumer.update(delta_mult, @camera_x, @camera_y, @camera_zoom, self.mouse_x, self.mouse_y)
end end
if !mouse_used # Finally process the dialouges
@dialouges.each do |dialouge| @dialouges.each do |dialouge|
dialouge.update(delta_mult, @camera_zoom, self.mouse_x, self.mouse_y) dialouge.update(delta_mult, @camera_zoom, self.mouse_x, self.mouse_y)
end end
end
case @current_tool case @current_tool
when 'delete' when 'delete'
@@ -291,6 +330,15 @@ class NumFactory < Gosu::Window
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
if consumer.draw_y <= HEIGHT && consumer.draw_y >= 0 if consumer.draw_y <= HEIGHT && consumer.draw_y >= 0
@@ -309,6 +357,7 @@ class NumFactory < Gosu::Window
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)
@@ -318,10 +367,11 @@ class NumFactory < Gosu::Window
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 if @cursor == @cursor_image
@cursor.draw(self.mouse_x - 16, self.mouse_y - 16, 10) @cursor.draw(self.mouse_x - @cursor_offset, self.mouse_y - @cursor_offset, 10)
else 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) @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 end
Gosu.draw_rect(self.mouse_x - 2, self.mouse_y - 2, 4, 4, Gosu::Color::RED)
end end
end end
+2 -1
View File
@@ -5,7 +5,7 @@ PRODUCER_DEBUG = false
BORDER = 2 BORDER = 2
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
@@ -28,6 +28,7 @@ class Producer
puts "X: #{@x}, Y: #{@y}" puts "X: #{@x}, Y: #{@y}"
@tooltip = @parent.register_dialouge(@x, @y, @box_size, @box_size, "Produces #{@rate} number per second", 500) @tooltip = @parent.register_dialouge(@x, @y, @box_size, @box_size, "Produces #{@rate} number per second", 500)
@size_x = @size_y = 1
end end