forked from bionickatana/number_factory
693f5b83e9
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: bionickatana/number_factory#8 Co-authored-by: nathan <nathan@hintonclan.org> Co-committed-by: nathan <nathan@hintonclan.org>
243 lines
7.7 KiB
Ruby
243 lines
7.7 KiB
Ruby
## Nathan Hinton
|
|
## Main entry point for the game. Sets up the world and holds the main loop
|
|
|
|
|
|
require 'gosu'
|
|
require 'yaml'
|
|
|
|
require './producer.rb'
|
|
require './consumer.rb'
|
|
|
|
# Viewport resolution
|
|
WIDTH = Gosu::screen_width
|
|
HEIGHT = Gosu::screen_height
|
|
BOX_SIZE = 64
|
|
|
|
# Default game settings
|
|
GAME_SAVE_DIRECTORY = 'game_save_data'
|
|
GAME_WIDTH = 101 # Odd numbers look best, in squares
|
|
GAME_HEIGHT = 101
|
|
GAME_PRODUCER_CHANCE = 0.01
|
|
GAME_PRODUCER_VALUE_MULT = 0.1
|
|
GAME_PRODUCER_BASE_SPEED = 1
|
|
|
|
# Camera settings
|
|
CAMERA_MOVE_RANGE = 10
|
|
CAMERA_MOVE_SPEED = 1
|
|
CAMERA_MOVE_MAX_SPEED = 5
|
|
CAMERA_MIN_ZOOM = 16 # Boxes across
|
|
CAMERA_MAX_ZOOM = 80 # Boxes across
|
|
|
|
class NumFactory < Gosu::Window
|
|
def initialize
|
|
super WIDTH, HEIGHT, :fullscreen => true
|
|
self.caption = "Number factory"
|
|
|
|
@background_color = Gosu::Color::BLUE
|
|
|
|
@camera_x = 0
|
|
@camera_y = 0
|
|
@camera_boxes = 30 # Default zoom
|
|
@camera_zoom = 1
|
|
@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
|
|
|
|
# Load from file or initialize a new game
|
|
begin
|
|
game_save_data = YAML.load_file("#{GAME_SAVE_DIRECTORY}/positions.yaml")
|
|
puts game_save_data
|
|
# Load from file OR generate new save file
|
|
@producers = [
|
|
Producer.new(0, 0, 1, 1),
|
|
Producer.new(1000, 1000, 1, 1),
|
|
Producer.new(2000, 2000, 1, 1),
|
|
]
|
|
@consumers = []
|
|
@belts = []
|
|
|
|
rescue Errno::ENOENT # File does not exist
|
|
puts "Generating new game..."
|
|
@game_width = GAME_WIDTH
|
|
@game_height = GAME_HEIGHT
|
|
|
|
@producers = []
|
|
@consumers = [] # Consumer in center
|
|
@belts = []
|
|
|
|
|
|
# Loop through and place producers
|
|
center_x = ((@game_width - 1) / 2).to_i
|
|
center_y = ((@game_height - 1) / 2).to_i
|
|
|
|
@consumers.append(
|
|
Consumer.new(center_x, center_y, BOX_SIZE, WIDTH, HEIGHT),
|
|
)
|
|
|
|
# The value of the producer is proportional to the distance from the center
|
|
((@game_width).to_i).times do |xx|
|
|
(@game_height).to_i.times do |yy|
|
|
if rand < GAME_PRODUCER_CHANCE
|
|
# Place a producer:
|
|
@producers.append(
|
|
Producer.new(
|
|
xx,
|
|
yy,
|
|
(Math.sqrt((xx - center_x)**2 + (yy - center_y) ** 2) * GAME_PRODUCER_VALUE_MULT).to_i,
|
|
GAME_PRODUCER_BASE_SPEED,
|
|
BOX_SIZE,
|
|
WIDTH,
|
|
HEIGHT,
|
|
)
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end # End file loading
|
|
|
|
# Move the camera to the center of the map:
|
|
@camera_x = @game_width / 2
|
|
@camera_y = @game_height / 2
|
|
|
|
# Render the background
|
|
@background = Gosu.render(@game_width * BOX_SIZE, @game_height * BOX_SIZE) {
|
|
im = Gosu::Image.new('assets/images/background_square.png', {:tileable => true})
|
|
zoom = BOX_SIZE / 30.0
|
|
(@game_width).to_i.times do |ww|
|
|
puts ww
|
|
(@game_height).to_i.times do |hh|
|
|
im.draw(ww * BOX_SIZE, hh * BOX_SIZE, 0, zoom, zoom)
|
|
end
|
|
end
|
|
}
|
|
|
|
@tick_time = Time.now()
|
|
@delta_time = 0
|
|
|
|
end
|
|
|
|
|
|
def button_down(id)
|
|
if id == Gosu::KB_ESCAPE
|
|
close
|
|
elsif [Gosu::MS_WHEEL_UP, Gosu::KB_Z].include? id
|
|
@camera_boxes -= 2
|
|
if @camera_boxes < CAMERA_MIN_ZOOM
|
|
@camera_boxes = CAMERA_MIN_ZOOM
|
|
end
|
|
@camera_zoom = WIDTH / (@camera_boxes * BOX_SIZE).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
|
|
elsif [Gosu::MS_WHEEL_DOWN, Gosu::KB_X].include? id
|
|
@camera_boxes += 2
|
|
if @camera_boxes > CAMERA_MAX_ZOOM
|
|
@camera_boxes = CAMERA_MAX_ZOOM
|
|
end
|
|
@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_y_zoom_offset = HEIGHT.to_f / (@camera_boxes * BOX_SIZE * 2).to_f
|
|
elsif id == Gosu::KB_DOWN
|
|
@camera_y += 1
|
|
elsif id == Gosu::KB_UP
|
|
@camera_y -= 1
|
|
elsif id == Gosu::KB_LEFT
|
|
@camera_x -= 1
|
|
elsif id == Gosu::KB_RIGHT
|
|
@camera_x += 1
|
|
elsif id == Gosu::KB_SPACE
|
|
@camera_boxes = 30
|
|
@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_y_zoom_offset = HEIGHT.to_f / (@camera_boxes * BOX_SIZE * 2).to_f
|
|
else
|
|
super
|
|
end
|
|
end
|
|
|
|
|
|
## Called every frame
|
|
def update
|
|
@delta_time = Time.now() - @tick_time
|
|
delta_mult = @delta_time * 30
|
|
#puts "Time: #{@delta_time}, Mult: #{delta_mult}" # Timing debug
|
|
@tick_time = Time.now()
|
|
|
|
### CAMERA ###
|
|
# Move the camera if needed
|
|
if self.mouse_x < CAMERA_MOVE_RANGE
|
|
@camera_x -= ([(CAMERA_MOVE_SPEED * ((CAMERA_MOVE_RANGE - self.mouse_x ) / 5)).to_i, CAMERA_MOVE_MAX_SPEED].min * delta_mult)
|
|
elsif self.mouse_x > WIDTH - CAMERA_MOVE_RANGE
|
|
@camera_x += ([(CAMERA_MOVE_SPEED * ((CAMERA_MOVE_RANGE - (WIDTH - self.mouse_x) ) / 2)).to_i, CAMERA_MOVE_MAX_SPEED].min * delta_mult)
|
|
end
|
|
|
|
if self.mouse_y < CAMERA_MOVE_RANGE
|
|
@camera_y -= ([(CAMERA_MOVE_SPEED * ((CAMERA_MOVE_RANGE - self.mouse_y ) / 2)).to_i, CAMERA_MOVE_MAX_SPEED].min * delta_mult)
|
|
elsif self.mouse_y > HEIGHT - CAMERA_MOVE_RANGE
|
|
@camera_y += ([(CAMERA_MOVE_SPEED * ((CAMERA_MOVE_RANGE - (HEIGHT - (self.mouse_y + 1)) ) / 2)).to_i, CAMERA_MOVE_MAX_SPEED].min * delta_mult)
|
|
end
|
|
|
|
# Prevent camera from leaving the screen
|
|
@camera_x = [@camera_x, 0].max
|
|
@camera_x = [@camera_x, @game_width].min
|
|
@camera_y = [@camera_y, 0].max
|
|
@camera_y = [@camera_y, @game_width].min
|
|
|
|
### ITEMS ###
|
|
@producers.each do |producer|
|
|
producer.update(delta_mult, @camera_x, @camera_y, @camera_zoom)
|
|
end
|
|
|
|
@belts.each do |belt|
|
|
belt.update(delta_mult)
|
|
end
|
|
|
|
@consumers.each do |consumer|
|
|
consumer.update(delta_mult, @camera_x, @camera_y, @camera_zoom)
|
|
end
|
|
end
|
|
|
|
## Called when OS wants to update window.
|
|
def draw
|
|
# Draw mouse coords:
|
|
onscreen_items = 0
|
|
@background.draw(
|
|
(((((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)),
|
|
0,
|
|
@camera_zoom,
|
|
@camera_zoom
|
|
)
|
|
|
|
@producers.each do |producer|
|
|
if producer.draw_x <= WIDTH && producer.draw_x >= 0
|
|
if producer.draw_y <= HEIGHT && producer.draw_y >= 0
|
|
producer.draw()
|
|
onscreen_items += 1
|
|
end
|
|
end
|
|
end
|
|
|
|
@consumers.each do |consumer|
|
|
if consumer.draw_x <= WIDTH && consumer.draw_x >= 0
|
|
if consumer.draw_y <= HEIGHT && consumer.draw_y >= 0
|
|
consumer.draw()
|
|
onscreen_items += 1
|
|
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)
|
|
end
|
|
end
|
|
|
|
NumFactory.new.show
|
|
|
|
|