I can’t figure out why clicking a shape is returning false for hitTestPoint.
I have a Button class which defines a click method. I use this method in my splashScene for a button to start the game and it works fine.
In the splashScene (and it will eventually be added to all other scenes) I’ve added a button for raising and lowering the volume of the background music. The code for this is below.
There is a group for the button. Added to this group is an image of text as a label for the button and the image of the button itself.
Added to the button is a shape overlaying the top half of the button, the area with the “up” arrow. Once I get this working, the opacity of this shape will be set to 0 and another shape will be added overlaying the bottom half of the button, the area with the down area, to lower the volume.
The shape has a click event listener which uses the same button class click method I used for the start button, which works fine. But when I click the shape, the hitTestPoint returns false and so, of course, nothing happens. I can’t figure out why it doesn’t return true.
CODE BELOW:
--add music volume button group
local musicVolumeButtonGroup = Sprite.new()
musicVolumeButtonGroup:setAnchorPoint( 0 , 0 )
musicVolumeButtonGroup:setPosition( conf.gameWidth * 0.87, conf.gameHeight * 0.6 )
self:addChildAt(musicVolumeButtonGroup, 3)
--add text image to button group
local musicVolumeText = Bitmap.new(Texture.new("images/musicVolumeText.png", true))
musicVolumeText:setAnchorPoint( 0 , 0 )
musicVolumeText:setPosition( 0 , 0 )
musicVolumeButtonGroup:addChildAt( musicVolumeText , 1 )
--add button image to button group
local musicVolumeButton = Bitmap.new(Texture.new("images/musicVolumeButton.png", true))
musicVolumeButton:setAnchorPoint( 0 , 0 )
musicVolumeButton:setPosition( 0 , musicVolumeText:getHeight() * 1.1 )
musicVolumeButtonGroup:addChildAt( musicVolumeButton , 1 )
--add volume up shape to button
local volumeUpButton = Shape.new()
volumeUpButton:setLineStyle( 2, color.yellow, 1 )
volumeUpButton:setFillStyle( Shape.SOLID, color.blue, 0.8 )
local volumeUpButtonX = musicVolumeButton:getWidth()
local volumeUpButtonY = musicVolumeButton:getHeight() / 2
volumeUpButton:beginPath()
volumeUpButton:moveTo( 0 , volumeUpButtonY )
volumeUpButton:lineTo( volumeUpButtonX , volumeUpButtonY )
volumeUpButton:lineTo( volumeUpButtonX , 0 )
volumeUpButton:lineTo( 0 , 0 )
volumeUpButton:closePath()
volumeUpButton:endPath()
volumeUpButton:setAnchorPoint( 0 , 0 )
volumeUpButton:setPosition( 0, 0 )
volumeUpButton:addEventListener("click", function()
if backgroundMusicVolume < 1 then backgroundMusicVolume = backgroundMusicVolume + 0.1 end
end)
musicVolumeButton:addChildAt ( volumeUpButton , 1 )
Comments
Fragmenter - animated loop machine and IKONOMIKON - the memory game
Below is the code for the Button class, which includes the "click" event which is called in the event listener. (Note: The print statement in the button class code is how I know hitTestPoint is returning false.)
BUTTON CLASS CODE:
Button = Core.class(Sprite)
function Button:init(sprite)
self:addChild(sprite)
self:addEventListener(Event.MOUSE_UP, self.onMouseUp, self)
end
-- This function does 3 things
-- 1. Checks if click point is in object.
-- 2. Stops propagation of this event.
-- 3. MOST IMPORTANT-Tells program to do task specific to the button which called this function.
function Button:onMouseUp(event)
print("self:hitTestPoint(event.x, event.y)= ", self:hitTestPoint(event.x, event.y))
if self:hitTestPoint(event.x, event.y) then
event:stopPropagation()
local clickEvent = Event.new("click")
self:dispatchEvent(clickEvent)
end
end
https://github.com/gideros/Button
or at least have a look how that works.
Fragmenter - animated loop machine and IKONOMIKON - the memory game
I well understand that you and others are volunteers and I never expect "immediate responses" and I'm grateful for the time you put into helping neophytes like me.
Regarding "why don't you use the 'standard' button class", frankly I wasn't aware there is one and I will certanly take a look at it.
I have been following pretty closely ar2rsawseen's book and my button class is pretty much taken from there. But again, I'll look at using the standard one you referenced. Thanks again.
Fragmenter - animated loop machine and IKONOMIKON - the memory game
The standard button class is in the examples that go with Gideros Studio
Also see my class buttons - In my class, you can press several buttons simultaneously
http://giderosmobile.com/forum/discussion/7200/button-class-is-multitouch#latest
Likes: keszegh, antix
https://play.google.com/store/apps/developer?id=razorback456
мій блог по гідерос https://simartinfo.blogspot.com
Слава Україні!
keszegh, I'll chang to the standard button class in my program and see what happens.
my class also knows how to work without a multitouch
https://play.google.com/store/apps/developer?id=razorback456
мій блог по гідерос https://simartinfo.blogspot.com
Слава Україні!
I changed thebutton class file to the one in the examples folder of Gideros. In my splashScene there's a button to start the game. In the code for this button, I changed from a single local variable for the image for the button to 2 local variables, "up" and "down" for the images and then changed the Button.new() to include the two images.
Here is the code (I don't have specific up and down buttons yet, so I just used images of 2 different buttons I already have. I'll change them when this works.):
local up = Bitmap.new(Texture.new("images/restartButton.png", true))
local down = Bitmap.new(Texture.new("images/quitButton.png", true))
local startButton = Button.new( up, down )
When I run the project, at first, it performs as expected - displaying the button. I expected that when I clicked the botton, the button image would change to the other image and change back when released and it would perform the "click" function, which in this case is change to the playScene. However, when I click the button, it just changes the image and stops and produces the output below in the console.
classes/button.lua:98: bad argument #1 to 'contains' (Sprite expected, got nil)
stack traceback:
classes/button.lua:98: in function 'updateVisualState'
classes/button.lua:17: in function 'init'
[string "property.lua"]:52: in function '__new'
[string "property.lua"]:59: in function 'new'
scenes/PlayScene.lua:94: in function 'init'
[string "property.lua"]:52: in function '__new'
[string "property.lua"]:59: in function 'new'
classes/scenemanager.lua:287: in function 'changeScene'
Here are lines 98, 99 and 100 of button.lua
if self:contains(self.downState) then
self:removeChild(self.downState)
end
I wondered if there was a problem with the function in the event listener. Below is the code. You'll see that I commented out the sceneManager line and added a print statement. When I did this I got the expected results: on clicking, the button image changed, the print statement printed and the button image changed back.
So why does the sceneManager line "break" this? It worked fine with my simpler Button class.
startButton:addEventListener("click", function()
print("start button clicked")
--sceneManager:changeScene("play", conf.transitionTime, conf.transition, conf.easing)
end)
While I'm waiting for a solution for my last comment, I decided to try something UNRELATED. I decided I don't necessarily want to have an up state and a down state and therefore have to create 2 images. Of course, I could just put the same variable for both images in the function call, i.r., local startButton = Button.new( buttonImage , buttonImage ).
But I decided if I'm only using one image, I'd rather only put one image in the function call, so in the init function I replaced
self.downState = downState
with
if not downState then
print("Did you intend not to add an image for the down state?")
self.downState = upState
else
self.downState = downState
end
So now, I can enter 2 images if I want to or, if I enter just one image, it will use the same image for both states (and give me a warning in the console).
Is there any reason I shouldn't do this?
self:setColorTransform(2, 2, 2, 1)
**ps
self.downState = upState --
it makes no sense to do so!!!
https://play.google.com/store/apps/developer?id=razorback456
мій блог по гідерос https://simartinfo.blogspot.com
Слава Україні!
Fragmenter - animated loop machine and IKONOMIKON - the memory game
b=Button.new(buttonBmp,buttonBmp)
Fragmenter - animated loop machine and IKONOMIKON - the memory game
https://play.google.com/store/apps/developer?id=razorback456
мій блог по гідерос https://simartinfo.blogspot.com
Слава Україні!
"the error is not with the button you pressed but with a button which is created when entering the new scene" is the problem. I went to playScene (the new scene being entered) and commented out all of the listeners. When I clicked the start button, it went to the playScene, no problem.
Now I just have to make changes throughout the project based on the new Button class.
Thanks again, keszegh!
And I still have to see if the new Button class solves the original problem with the hitTestPoint.
Likes: keszegh, antix