Skip to content

Commit

Permalink
Merge branch 'master' into add-i18n-support
Browse files Browse the repository at this point in the history
  • Loading branch information
pablofullana committed Aug 25, 2017
2 parents dfc732b + 4bcf2a2 commit 9c40d12
Show file tree
Hide file tree
Showing 23 changed files with 515 additions and 54 deletions.
4 changes: 4 additions & 0 deletions exe/goby
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env ruby

require 'goby'
Goby::Scaffold::simple "goby-project"
1 change: 1 addition & 0 deletions goby.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Gem::Specification.new do |spec|
spec.license = "MIT"

spec.files = Dir["{lib}/**/*", "LICENSE", "README.md" ]
spec.files = Dir["{exe}/**/*", "{lib}/**/*", "{res}/**/*", "LICENSE", "README.md" ]
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
Expand Down
5 changes: 5 additions & 0 deletions lib/goby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
require 'i18n'
I18n.load_path = Dir["#{File.expand_path(File.dirname(__FILE__))}/goby/config/locales/*.yml"]

# Import order matters.

require 'goby/scaffold'
require 'goby/extension'
require 'goby/util'
require 'goby/world_command'
require 'goby/music'
require 'goby/driver'

require 'goby/battle/battle_command'
Expand All @@ -22,6 +26,7 @@
require 'goby/entity/player'

require 'goby/event/event'
require 'goby/event/chest'
require 'goby/event/npc'
require 'goby/event/shop'

Expand Down
5 changes: 5 additions & 0 deletions lib/goby/driver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,25 @@

module Goby

include Music
include WorldCommand

# Runs the main game loop.
#
# @param [Player] player the player of the game.
def run_driver(player)

play_music(player.map.music) if player.map.music
input = player_input prompt: '> '

while (input.casecmp("quit").nonzero?)
interpret_command(input, player)
play_music(player.map.music) if player.map.music
input = player_input prompt: '> '
end

stop_music

end

end
25 changes: 16 additions & 9 deletions lib/goby/entity/entity.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,22 +78,29 @@ def add_item(item, amount = 1)
@inventory.push(Couple.new(item, amount))
end

# Adds the specified gold and treasure item to the inventory.
# Adds the specified gold and treasures to the inventory.
#
# @param [Integer] gold the amount of gold.
# @param [Item] treasure the treasure item.
def add_rewards(gold, treasure)
if ((gold.positive?) || treasure)
type("Rewards:\n")
# @param [[Item]] treasures the list of treasures.
def add_loot(gold, treasures)
type("Loot: ")
if ((gold.positive?) || (treasures && treasures.any?))
print "\n"
if gold.positive?
type("* #{gold} gold\n")
add_gold(gold)
end
if treasure
type("* #{treasure.name}\n")
add_item(treasure)
if treasures && treasures.any?
treasures.each do |treasure|
unless treasure.nil?
type("* #{treasure.name}\n")
add_item(treasure)
end
end
end
print "\n"
print "\n"
else
type("nothing!\n\n")
end
end

Expand Down
26 changes: 15 additions & 11 deletions lib/goby/entity/player.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,24 @@ class Player < Entity
# @param [Hash] outfit the collection of equippable items currently worn.
# @param [Map] map the map on which the player is located.
# @param [Couple(Integer,Integer)] location the 2D index of the map (the exact tile).
def initialize(name: "Player", stats: {}, inventory: [], gold: 0, battle_commands: [], outfit: {}, map: DEFAULT_MAP,
location: DEFAULT_LOCATION)
def initialize(name: "Player", stats: {}, inventory: [], gold: 0, battle_commands: [],
outfit: {}, map: nil, location: nil)
super(name: name, stats: stats, inventory: inventory, gold: gold, battle_commands: battle_commands, outfit: outfit)

@map = DEFAULT_MAP
@location = DEFAULT_LOCATION
@saved_maps = Hash.new

# Ensure that the map and the location are valid.
new_map = DEFAULT_MAP
new_location = DEFAULT_LOCATION
if (map && location)

y = location.first; x = location.second

if (map.in_bounds(y,x) && map.tiles[y][x].passable)
move_to(location, map)
new_map = map
new_location = location
end
end

move_to(new_location, new_map)
@saved_maps = Hash.new
end

# Engages in battle with the specified monster.
Expand Down Expand Up @@ -103,7 +104,7 @@ def battle(monster)
gold = rewards.first
treasure = rewards.second

add_rewards(gold, treasure)
add_loot(gold, [treasure])
end

end
Expand Down Expand Up @@ -231,13 +232,16 @@ def move_to(coordinates, map = @map)

y = coordinates.first; x = coordinates.second

# Save the map.
@saved_maps[@map.name] = @map if @map

# Prevents moving onto nonexistent and impassable tiles.
if (!map.in_bounds(y,x) || (!map.tiles[y][x].passable))
describe_tile(self)
return
end

@map = map
@map = @saved_maps[map.name] ? @saved_maps[map.name] : map
@location = coordinates
tile = @map.tiles[y][x]

Expand Down Expand Up @@ -337,7 +341,7 @@ def update_map(coordinates = @location)
end
end

attr_reader :map, :location
attr_reader :map, :location, :saved_maps

end

Expand Down
33 changes: 33 additions & 0 deletions lib/goby/event/chest.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require 'goby'

module Goby

# A chest containing gold and/or items.
class Chest < Event

# @param [Integer] mode convenient way for a chest to have multiple actions.
# @param [Boolean] visible whether the chest can be seen/activated.
# @param [Integer] gold the amount of gold in this chest.
# @param [[Item]] treasures the items found in this chest.
def initialize(mode: 0, visible: true, gold: 0, treasures: [])
super(mode: mode, visible: visible)
@command = "open"
@gold = gold
@treasures = treasures
end

# The function that runs when the player opens the chest.
#
# @param [Player] player the one opening the chest.
def run(player)
type("You open the treasure chest...\n\n")
sleep(1) unless ENV['TEST']
player.add_loot(@gold, @treasures)
@visible = false
end

attr_reader :gold, :treasures

end

end
5 changes: 3 additions & 2 deletions lib/goby/map/map.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ class Map
# @param [String] name the name.
# @param [[Tile]] tiles the content of the map.
# @param [Couple(Integer, Integer)] regen_location respawn-on-death coordinates.
def initialize(name: "Map", tiles: [[Tile.new]], regen_location: Couple.new(0,0))
def initialize(name: "Map", tiles: [[Tile.new]], regen_location: Couple.new(0,0), music: nil)
@name = name
@tiles = tiles
@regen_location = regen_location
@music = music
end

# Returns true when @tiles[y][x] is an existing index of @tiles.
Expand Down Expand Up @@ -39,7 +40,7 @@ def ==(rhs)
return @name == rhs.name
end

attr_accessor :name, :tiles, :regen_location
attr_accessor :name, :tiles, :regen_location, :music

end

Expand Down
64 changes: 64 additions & 0 deletions lib/goby/music.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
module Goby

# Methods for playing/stopping background music (BGM).
module Music

# Specify the program that should play the music.
# Without overwriting, it is set to a default (see @@program).
#
# @param [String] name the name of the music-playing program.
def set_program(name)
@@program = name
end

# Specify if music should play or not.
# May be useful to stop/start music for dramatic effect.
#
# @param [Boolean] flag true iff music should play.
def set_playback(flag)
@@playback = flag
end

# Starts playing the music from the specified file.
# This has only been tested on Ubuntu w/ .mid files.
#
# @param [String] filename the file containing the music.
def play_music(filename)
return unless @@playback

if (filename != @@file)
stop_music
@@file = filename

# This thread loops the music until one calls #stop_music.
@@thread = Thread.new {
while (true)
Process.wait(@@pid) if @@pid
@@pid = Process.spawn("#{@@program} #{filename}", :out=>"/dev/null")
end
}
end
end

# Kills the music process and the looping thread.
def stop_music
return unless @@playback

Process.kill("SIGKILL", @@pid) if @@pid
@@pid = nil

@@thread.kill if @@thread
@@thread = nil

@@file = nil
end

@@file = nil
@@pid = nil
@@playback = false
@@program = "timidity"
@@thread = nil

end

end
36 changes: 36 additions & 0 deletions lib/goby/scaffold.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module Goby

# Functions for scaffolding starter projects.
module Scaffold

# Simple starter project w/o testing.
#
# @param [String] project the project name.
def self.simple(project)

# TODO: detect existence of project folder.

# Make the directory structure.
Dir.mkdir project
dirs = [ '', 'battle', 'entity',
'event', 'item', 'map' ]
dirs.each do |dir|
Dir.mkdir "#{project}/src/#{dir}"
end

# Create the source files.
gem_location = %x[gem which goby].chomp "/lib/goby.rb\n"
files = { '.gitignore': '../gitignore',
'src/main.rb': 'main.rb',
'src/map/farm.rb': 'farm.rb' }
files.each do |dest, source|
File.open("#{project}/#{dest.to_s}", 'w') do |w|
w.write(File.read "#{gem_location}/res/scaffold/simple/#{source}")
end
end

end

end

end
50 changes: 50 additions & 0 deletions res/scaffold/gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
*.gem
*.rbc
/.config
/coverage/
/InstalledFiles
/pkg/
/spec/reports/
/spec/examples.txt
/test/tmp/
/test/version_tmp/
/tmp/

# Used by dotenv library to load environment variables.
# .env

## Specific to RubyMotion:
.dat*
.repl_history
build/
*.bridgesupport
build-iPhoneOS/
build-iPhoneSimulator/

## Specific to RubyMotion (use of CocoaPods):
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# vendor/Pods/

## Documentation cache and generated files:
/.yardoc/
/_yardoc/
/doc/
/rdoc/

## Environment normalization:
/.bundle/
/vendor/bundle
/lib/bundler/man/

# for a library or gem, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# Gemfile.lock
# .ruby-version
# .ruby-gemset

# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
.rvmrc
15 changes: 15 additions & 0 deletions res/scaffold/simple/farm.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# This is an example of how to create a Map. You can
# define the name, where to respawn, and the 2D display of
# the Map - each point is referred to as a Tile.
class Farm < Map
def initialize
super(name: "Farm", regen_location: Couple.new(2,2))

# Define the main tiles on this map.
grass = Tile.new(description: "You are standing on some grass.")

# Fill the map with "grass."
@tiles = Array.new(5) { Array.new(5) { grass.clone } }

end
end
Loading

0 comments on commit 9c40d12

Please sign in to comment.