undefined method `pause' for #<Ruby2D::Sound:0x000002728db4b250 #path="musics/machinegun.mp3", #data=#<Object:0x000002728db4b1d8>> (NoMethodError)
pause or stop etc is a built-in method in ruby2d but I can not seem to make this work. I think that a specific part of ruby2d method might ran into an error because the play method, which is in the same category, still works fine but not the other aforementioned functions.
assault_rifle = Sound.new('musics/machinegun.mp3')
on :key_held do |event|
if event.key == 'k'
mainscreen.player_fire_bullet
assault_rifle.play # this works!
end
if event.key == 'l'
assault_rifle.pause # this is just to test my theory that the method is broken
end
end
on :key_up do |event|
if event.key == 'k'
assault_rifle.stop #method error here?
end
end
For more information regarding ruby2d 's audio, you can read it here: https://www.ruby2d.com/learn/audio/
I hope some one could look into this
It's not a bug.
The Ruby2D::Sound class doesn't have a #pause method.
# frozen_string_literal: true
# Ruby2D::Sound
module Ruby2D
# Sounds are intended to be short samples, played without interruption, like an effect.
class Sound
attr_reader :path
attr_accessor :loop, :data
#
# Load a sound from a file
# #param [String] path File to load the sound from
# #param [true, false] loop If +true+ playback will loop automatically, default is +false+
# #raise [Error] if file cannot be found or music could not be successfully loaded.
def initialize(path, loop: false)
raise Error, "Cannot find audio file `#{path}`" unless File.exist? path
#path = path
#loop = loop
raise Error, "Sound `#{#path}` cannot be created" unless ext_init(#path)
end
# Play the sound
def play
ext_play
end
# Stop the sound
def stop
ext_stop
end
# Returns the length in seconds
def length
ext_length
end
# Get the volume of the sound
def volume
ext_get_volume
end
# Set the volume of the sound
def volume=(volume)
# Clamp value to between 0-100
ext_set_volume(volume.clamp(0, 100))
end
# Get the volume of the sound mixer
def self.mix_volume
ext_get_mix_volume
end
# Set the volume of the sound mixer
def self.mix_volume=(volume)
# Clamp value to between 0-100
ext_set_mix_volume(volume.clamp(0, 100))
end
end
end
Note:
Sounds are intended to be short samples, played without interruption, like an effect.
If you look at the linked example they are using the Music class which does.
song = Music.new('song.mp3')
# Play the music
song.play
# Pause the music
song.pause
The top level doc also states:
Music is for longer pieces which can be played, paused, stopped, resumed, and faded out, like a background soundtrack.
Related
I'm coding a game by taking a TDD first approach, and have gotten stuck because the test keeps stopping for user input (repo is here).
I want the test to simulate user input rather than prompting for it, as I've set up some let keywords and have tried to account for user input that comes in via gets.chomp.
Here is where the game prompts for user input:
game.rb
module ConnectFour
class Game
def start_game
puts 'Welcome to Connect Four.'
puts "Enter name of player 1 (red)"
player1name = gets.chomp
player1 = Player.new(player1name)
end
end
end
And here is the test code:
game_spec.rb
require 'spec_helper'
module ConnectFour
describe Game do
let(:game) { Game.new }
let(:player1name) { 'Bob' }
let(:player1) { Player.new(player1name) }
describe 'Instantiate game play objects' do
describe 'Create player 1' do
it 'Provide player 1 name' do
allow_any_instance_of(Kernel)
.to receive(:gets)
.and_return(player1name)
end
it 'Instantiate player 1' do
expect(player1.name).to eq player1name
end
end
end # describe 'Instantiate game play objects'
end # Describe 'Game'
end
So far I've tried encapsulating the gets.chomp in its own method as recommended here but this has no effect. I've also tried prefixing $stdin to gets.chomp statements in the Ruby code but yeah, that was pretty useless. I had asked a similar question here recently and thought I had understood how to simulate user input but obviously not... any help would be appreciated.
use allow_any_instance_of(Object) instead of Kernel. The module Kernel is included into Object. Kernel is not ever actually instantiated because it's a module.
kind of a small point, but it'd be more accurate if you stubbed gets to return a strinng ending in \n, otherwise you could remove the chomp from the tested functionn and the test will still pass
reproducable example
require 'rspec'
require 'rspec/expectations'
test_case = RSpec.describe "" do
it "" do
allow_any_instance_of(Object).to receive(:gets).and_return "something\n"
puts gets.chomp
end
end
test_case.run
Looks like my use of the proc maybe a bit off. I'm working on a tic-tac-toe game and using cucumber to test it's behavior. I've outlined the scenario that i want to fulfill and the step file that I'm using.
The Scenario,
Scenario: Making Bad Moves
Given I have a started Tic-Tac-Toe game
And it is my turn
And I am playing X
When I enter a position "A1" on the board
And "A1" is taken
Then computer should ask me for another position "B2"
And it is now the computer's turn
The step files say...
Given /^I have a started Tic\-Tac\-Toe game$/ do #
#game = TicTacToe.new(:player)
#game.player = "player" #
end
Given /^it is my turn$/ do #
#game.current_player.should eq "player"
end
Given /^I am playing X$/ do
#game = TicTacToe.new(:computer, :X)
#game.player_symbol.should eq :X
end
When /^"(.*?)" is taken$/ do |arg1|
#game.board[arg1.to_sy m] = :O **- # this is causing me to get a "undefined
method `[]=' for #
Given /^I am playing X$/ do
#game = TicTacToe.new(:computer, :X)
#game.player_symbol.should eq :X
end
My code that is attempting to satisfy the feature is:
def board
Proc.new do |get_player_move = :B2|
board_value = get_player_move
#board_locations[board_value]
end
I get this error: NoMethodError: undefined method[]=' for #`
Am i using the proc properly?
Your problem is that [] and []= are in fact different methods. When you type:
#game.board[arg1.to_sym] = :O
ruby reads it as:
#game.board.[]=(arg1.to_sym, :o)
and what you want is
#game.board.[](arg1.to_sym) = :O
To make sure ruby knows what you want do:
(#game.board[arg1.to_sym]) = :O
NOTE:
To be honest I am not sure why you are using Proc here at all, why not simple:
def board
#board_locations
end
I am writing an automated testing program which will test some web programs that are sometimes slow to load certain AJAX calls. For instance the user will click 'Query' which will result in a HTML 'loading' overlay for anywhere from 15 to 90 seconds. When the search completes, it will then update a table on the same page with the results.
So obviously I can increase the waiting time individually like so:
browser.td(:id => 'someId').when_present.some_action #=> will wait 30 seconds
browser.td(:id => 'someId').when_present(90).some_action #=> will wait *90* seconds
But is there a way to modify (in my case increase) the time so Watir-Webdriver always waits 90 seconds on .when_present like so:
browser.some_default = 90
browser.td(:id => 'someId').when_present.some_action #=> will wait *90* seconds
A few words of warning: Client timeout will not affect when_present. Nor will implicit wait.
Update: This monkey patch has been merged into watir-webdriver and so will no longer be needed in watir-webdriver v0.6.5. You will be able to set the timeout using:
Watir.default_timeout = 90
The wait methods are defined similar to:
def when_present(timeout = 30)
message = "waiting for #{selector_string} to become present"
if block_given?
Watir::Wait.until(timeout, message) { present? }
yield self
else
WhenPresentDecorator.new(self, timeout, message)
end
end
As you can see, the default timeout of 30 seconds is hard-coded. Therefore, there is no easy way to change it everywhere.
However, you could monkey patch the wait methods to use a default time and set it to what you want. The following monkey patch will set the default timeout to 90 seconds.
require 'watir-webdriver'
module Watir
# Can be changed within a script with Watir.default_wait_time = 30
#default_wait_time = 90
class << self
attr_accessor :default_wait_time
end
module Wait
class << self
alias old_until until
def until(timeout = Watir.default_wait_time, message = nil, &block)
old_until(timeout, message, &block)
end
alias old_while while
def while(timeout = Watir.default_wait_time, message = nil, &block)
old_while(timeout, message, &block)
end
end # self
end # Wait
module EventuallyPresent
alias old_when_present when_present
def when_present(timeout = Watir.default_wait_time, &block)
old_when_present(timeout, &block)
end
alias old_wait_until_present wait_until_present
def wait_until_present(timeout = Watir.default_wait_time)
old_wait_until_present(timeout)
end
alias old_wait_while_present wait_while_present
def wait_while_present(timeout = Watir.default_wait_time)
old_wait_while_present(timeout)
end
end # EventuallyPresent
end # Watir
Include the patch after the watir webdriver code is loaded.
Let me preface by stating I'm a "new" programmer - an IT guy trying his hand at his first "real" problem after working through various tutorials.
So - here is what I'm trying to do. I'm watching a directory for a .csv file - it will be in this format: 999999_888_filename.csv
I want to return each part of the "_" filename as a variable to pass on to another program/script for some other task. I have come up w/ the following code:
require 'rubygems'
require 'fssm'
class Watcher
def start
monitor = FSSM::Monitor.new(:directories => true)
monitor.path('/data/testing/uploads') do |path|
path.update do |base, relative, ftype|
output(relative)
end
path.create do |base, relative, ftype|
output(relative)
end
path.delete { |base, relative, ftype| puts "DELETED #{relative} (#{ftype})" }
end
monitor.run
end
def output(relative)
puts "#{relative} added"
values = relative.split('_',)
sitenum = values[0]
numrecs = values[1]
filename = values[2]
puts sitenum
end
end
My first "puts" gives me the full filename (it's just there to show me the script is working), and the second puts returns the 'sitenum'. I want to be able to access this "outside" of this output method. I have this file (named watcher.rb) in a libs/ folder and I have a second file in the project root called 'monitor.rb' which contains simply:
require './lib/watcher'
watcher = Watcher.new
watcher.start
And I can't figure out how to access my 'sitenum', 'numrecs' and 'filename' from this file. I'm not sure if it needs to be a variable, instance variable or what. I've played around w/ attr_accessible and other things, and nothing works. I decided to ask here since I've been spinning my wheels for a couple of things, and I'm starting to confuse myself by searching on my own.
Thanks in advance for any help or advice you may have.
At the top of the Watcher class, you're going to want to define three attr_accessor declarations, which give the behavior you want. (attr_reader if you're only reading, attr_writer if you're only writing, attr_accessor if both.)
class Watcher
attr_accessor :sitenum, :numrecs, :filename
...
# later on, use # for class variables
...
#sitenum = 5
...
end
Now you should have no problem with watcher.sitenum etc. Here's an example.
EDIT: Some typos.
In addition to Jordan Scales' answer, these variable should initialized
class Watcher
attr_accessor :sitenum, :numrecs, :filename
def initialize
#sitenum = 'default value'
#numrecs = 'default value'
#filename = 'default value'
end
...
end
Otherwise you'll get uninformative value nil
[EDIT NOTE: Noticed I had put the mutex creation in the constructor. Moved it and noticed no change.]
[EDIT NOTE 2: I changed the call to app.exec in a trial run to
while TRUE do
app.processEvents()
puts '."
end
I noticed that once the Soap4r service started running no process events ever got called again]
[EDIT NOTE 3: Created an associated question here: Thread lockup in ruby with Soap4r
I'm attempting to write a ruby program that receives SOAP commands to draw on a monitor (thus allowing remote monitor access). I've put together a simple test app to prototype the idea. The graphic toolkit is QT. I'm having what I assume is a problem with locking. I've added calls to test the methods in the server in the code shown. The server side that I'm testing right now is:
require 'rubygems'
require 'Qt4'
require 'thread'
require 'soap/rpc/standaloneserver'
class Box < Qt::Widget
def initialize(parent = nil)
super
setPalette(Qt::Palette.new(Qt::Color.new(250,0,0)))
setAutoFillBackground(true)
show
end
end
class SOAPServer < SOAP::RPC::StandaloneServer
##mutex = Mutex.new
def initialize(* args)
super
# Exposed methods
add_method(self, 'createWindow', 'x', 'y', 'width', 'length')
end
def createWindow(x, y, width, length)
puts 'received call'
windowID = 0
puts #boxList.length
puts #parent
##mutex.synchronize do
puts 'in lock'
box = Box.new(#parent)
box.setGeometry(x, y, width, length)
windowID = #boxList.push(box).length
print "This:", windowID, "--\n"
end
puts 'out lock'
return windowID
end
def postInitialize (parent)
#parent = parent
#boxList = Array.new
end
end
windowSizeX = 400
windowSizeY = 300
app = Qt::Application.new(ARGV)
mainwindow = Qt::MainWindow.new
mainwindow.resize(windowSizeX, windowSizeY)
mainwindow.show
puts 'Attempting server start'
myServer = SOAPServer.new('monitorservice', 'urn:ruby:MonitorService', 'localhost', 4004)
myServer.postInitialize(mainwindow)
Thread.new do
puts 'Starting?'
myServer.start
puts 'Started?'
end
Thread.new do
myServer.createWindow(10,0,10,10)
myServer.createWindow(10,30,10,10)
myServer.createWindow(10,60,10,10)
myServer.createWindow(10,90,10,10)
end
myServer.createWindow(10,10,10,10)
Thread.new do
app.exec
end
gets
Now when I run this I get the following output:
Attempting server start
Starting?
received call
0
#<Qt::MainWindow:0x60fea28>
in lock
received call
0
#<Qt::MainWindow:0x60fea28>
This:1--
in lock
This:2--
out lock
At that point I hang rather than recieving the total of five additions I expect. Qt does display the squares defined by "createWindow(10,0,10,10)" and "createWindow(10,10,10,10)". Given that "This:1--" and "This:2--" show within a nexted in/out lock pair I'm assuming I'm using mutex horribly wrong. This is my first time with threading in Ruby.