Fractional x/y positions from touch events?

In that case, given my initial problem statement, how could dragging ever be made smooth on a 4x scale??

I would consider it absolutely necessary to have event.x return fractions, otherwise the whole content scaling thing loses an important component. Sure, I could file a feature request but I would actually consider this a bug (or at least a design flaw).

Divergent Monkey

I agree with you in some ways and understand your plight, but consider:

  1. Scaling from 320x480 to modern resolutions is a pretty big jump.  Most designs should start at no lower than 640 x 960 (or even 750x1334)
  • I typically tell clients to choose the primary target device and to set that as their resolution in config.lua.  
  • I further advise folks to use iPhone 6 or 6+ as their base.
  • Note: I totally understand liking 320x480 because it makes hand-calculations easy (I stayed there for a long time.)
  1. Implementing floating point values in the touch event(s) may have a hidden cost/performance side-effect.  
  2. Changing the current system to accommodate floating point values might also have a huge negative impact on current and past projects (one never knows what assumptions developers have made, but changing fundamentals is bound to cause issues.)

I know you said you’d have a lot of work ahead of you if you were forced to implement this at a higher resolution.  Can you elaborate on that a bit?  I ask because while there may be no way to get floating-point values from touches, there may still be ways to help you move this forward.

@ roaminggamer

You could definitely be right about possible negative performance effects of having floats in touch events. Also, just changing the behavior of event.x would be unwise. Instead adding e.g. event.xFract as a new property would be better at least from a backward compatibility standpoint.

In my project I have three versions of all images: 1x, 2x and 4x using a content size of 320 x 480 in config.lua. I assume that if I change the the content size to 640 x 960, all I would have to do is to delete all the 1x images and rename the remaining to 1x and 2x. A doubling of the content size paired with a doubling of the image size. In my code, I would then have to double all the image sizes in my newImageRect images as well as reposition in case I have used pixels instead of values like “display.contentWidth * 0.5”. Am I correct this far?

However, in “Modernizing the config.lua”, the argument is to have 1200 x 800 and above you mention 750 x 1334. These resolutions are not an even factor of 320 x 480, which I assume means that I would need images 2.5 times the size if e.g. using 1200 x 800. That in turn would then mean that I have to redraw them.  Or am I getting it wrong?

If you already have @2x assets, just rename them with out the extension and your @4x to @2x and then you could use a 640x960 screen which would improve things.

Yes, but wouldn’t I also have to resize them in the code? For example:

myImage = display.newImageRect(“myimage.png”, 50, 50)

myimage.png = 50 x 50 px

myimage@2x.png = 100 x 100 px

myimage@4x.png = 200 x 200 px

at content size 320 x 480

If I do as you suggest:

myimage.png = 100 x 100 px

myimage@2x.png = 200 x 200 px

at content size 640 x 960

If the image is still set as

myImage = display.newImageRect(“myimage.png”, 50, 50)

then it will not reflect the true 1x imge size. Wouldn’t that have a negative effect on image quality?

To my great surprise, I just received an email from the Corona staff that said:

This issue is resolved on our latest build version 2016.2994 and above.

I downloaded the latest daily build and sure enough, event.x now returns fractional values! Judging from Robs initial response, I suspect this is the way it should work and that the integer-thing was a bug.

Spoke too soon…

Fractional values are indeed returned, but they are not updated with the movement of the finger. The list below shows the event.x as I slowly drag an object, with printouts made in the “moved” phase. As you can see, the values are identical although the “moved” phase is obviously triggered and the object does not move on the screen until the value below shifts. So yes, fractional values are returned but the problem remains since it is the same fractional value that i returned although the finger is moved…

Dec 02 11:40:31.417 Event x: 78.50666809082
Dec 02 11:40:31.431 Event x: 78.50666809082
Dec 02 11:40:31.439 Event x: 78.50666809082
Dec 02 11:40:31.495 Event x: 78.50666809082
Dec 02 11:40:32.125 Event x: 78.50666809082
Dec 02 11:40:34.173 Event x: 78.50666809082
Dec 02 11:40:36.513 Event x: 78.50666809082
Dec 02 11:40:36.547 Event x: 78.50666809082
Dec 02 11:40:36.614 Event x: 78.50666809082
Dec 02 11:40:37.322 Event x: 78.50666809082
Dec 02 11:40:37.324 Event x: 78.50666809082
Dec 02 11:40:38.099 Event x: 78.50666809082
Dec 02 11:40:38.101 Event x: 80.213333129883
Dec 02 11:40:39.157 Event x: 80.213333129883
Dec 02 11:40:39.158 Event x: 80.213333129883
Dec 02 11:40:39.167 Event x: 80.213333129883
Dec 02 11:40:39.843 Event x: 80.213333129883
Dec 02 11:40:40.303 Event x: 80.213333129883
Dec 02 11:40:40.833 Event x: 80.213333129883
Dec 02 11:40:40.846 Event x: 80.213333129883
Dec 02 11:40:41.272 Event x: 80.213333129883
Dec 02 11:40:41.274 Event x: 80.213333129883
Dec 02 11:40:41.451 Event x: 80.213333129883
Dec 02 11:40:41.800 Event x: 81.919998168945
Dec 02 11:40:41.803 Event x: 81.919998168945
Dec 02 11:40:42.408 Event x: 81.919998168945
Dec 02 11:40:42.858 Event x: 81.919998168945
Dec 02 11:40:43.353 Event x: 81.919998168945
Dec 02 11:40:44.331 Event x: 81.919998168945
Dec 02 11:40:44.838 Event x: 81.919998168945
Dec 02 11:40:48.427 Event x: 81.919998168945
Dec 02 11:40:48.720 Event x: 81.919998168945
Dec 02 11:40:50.463 Event x: 81.919998168945
Dec 02 11:40:50.553 Event x: 81.919998168945
Dec 02 11:40:50.722 Event x: 81.919998168945
Dec 02 11:40:51.183 Event x: 81.919998168945
 

The returning of integers was not a bug but it kind of turned into a less desirable feature. Back in the day when every device was 320xsomething the precision for finger positions didn’t matter that much and it’s easier to work with integers than floats.

Today we need the factional values.  I’ll let the Engineer know about your findings.

Rob

Also, can you post your touch handling code here or at least a sample that demonstrates this?

Thanks

Rob

if (event.phase == "began") then -- Store current position touchObjectL.markX = touchObjectL.x touchObjectL.markY = touchObjectL.y elseif (event.phase == "moved") then print(event.x) -- Set new position of touch object touchObjectL.x = (event.x - event.xStart + touchObjectL.markX) touchObjectL.y = (event.y - event.yStart + touchObjectL.markY) elseif (event.phase == "ended" or event.phase == "cancelled") then .... end

touchObjectL is the object that is moved. Hope this snippet helps, please let me know if you need a more complete example. However, all you need is basically just to print the event.x in a “moved” phase to see what I mean.

We had a couple of engineers look into this today and we are basically just passing what the operating system provides us. Perhaps the device isn’t granular enough.

Rob

How is that possible?

The values in the list are printed in the “moved” phase which means that the device is obviously granular enough to detect the move. And if it can detect the move that has to mean that it knows that the coordinates of the touch point has changed, right? Also, how could the device even provide coordinates with that many decimals if it wasn’t able to detect/calculate them with more precision than that? I mean, it has to get those values from somewhere… It just doesn’t make sense.

If the values in my list above are what the operating system is passing on then it does not tell you all it knows about the coordinates. Then again, why would it only provide just a “few select values” when moving instead of all?

The test above was made on an iPhone 6 and I can reproduce it on an iPad as well. If that resolution is not granular enough, what is?

I took your code and make a simple test case:

local touchObjectL = display.newRect( 100, 100, 100, 100 ) local function touchHandler( event ) print(event.x, event.y) if (event.phase == "began") then -- Store current position touchObjectL.markX = touchObjectL.x touchObjectL.markY = touchObjectL.y elseif (event.phase == "moved") then print(event.x) -- Set new position of touch object touchObjectL.x = (event.x - event.xStart + touchObjectL.markX) touchObjectL.y = (event.y - event.yStart + touchObjectL.markY) end return true end touchObjectL:addEventListener("touch", touchHandler)

And it produced this on my iPad 4 running iOS 10.1

Dec 03 10:33:57.304 [Device] 129.53125 135.9375

Dec 03 10:33:57.304 [Device] 129.53125

Dec 03 10:33:57.371 [Device] 129.296875 135.9375

Dec 03 10:33:57.371 [Device] 129.296875

Dec 03 10:33:57.404 [Device] 129.0625 135.9375

Dec 03 10:33:57.405 [Device] 129.0625

                    [Device] 128.828125 135.9375

                    [Device] 128.828125

Dec 03 10:33:57.440 [Device] 128.59375 135.9375

Dec 03 10:33:57.440 [Device] 128.59375

Dec 03 10:33:57.571 [Device] 128.359375 135.9375

Dec 03 10:33:57.571 [Device] 128.359375

Dec 03 10:33:57.600 [Device] 128.125 135.9375

Dec 03 10:33:57.600 [Device] 128.125

Dec 03 10:33:57.644 [Device] 127.890625 135.9375

Dec 03 10:33:57.644 [Device] 127.890625

Dec 03 10:33:57.673 [Device] 127.1875 135.703125

When I tried this on my iPhone 6, I got results that are strange, but for the purpose of this post the strangeness is a red herring. What is important is that I got incremental values unlike your tests where you show that the value basically blocks for a bit before the change, on the iPhone 6 and iPad 4 I was getting incremental values.

Can you try the code above? 

What is your config.lua like?

What version of iOS are you running on your phone?

Rob

i think the easiest way to see this is to set a REALLY small content size (fe 40x60), then print not only the x,y’s from the event, but also an event counter - so that you can see on-screen how many times the same “quantized-to-content” integer values are returned (or adb logcat it looking for dup’d lines)

i can confirm that for build 2992 on Windows, and as built and running on an actual Android 5 device, that the attached code only returns quantized integer event coordinates.  (i’ve not tested if mac sim and/or ios device reproduce same)

a VERY SLOW drag across the width of device’s native 1080x1920 screen generates roughly 1000 events as expected, but only 40 unique integer event.x’s are ever reported, no fractional values whatsoever.

By increasing the content size to something more reasonable, you can get correspondingly LESS quantizing.  For app where touch/drag “precision” is required, 320x480 is nearly unusable. though 640x960 is often good enough.  By leaving out content size entirely config.lua, thus using device native pixel dimensions, completely eliminates the quantizing effect- though that defeats all of Corona’s self-scaling nicety features.

@Rob: using your example, I can still get duplicate event.x values from consecutive “moved” phase printouts moving really slow but much fewer than in my original code. I will look into my code and see if I can find anything else that causes it. I use 2016.2995, iOS 10.1.1 and my config.lua is:

local aspectRatio = display.pixelHeight / display.pixelWidth application = { content = { width = aspectRatio \> 1.5 and 640 or math.floor(960 / aspectRatio), height = aspectRatio \< 1.5 and 960 or math.floor(640 \* aspectRatio), scale = "letterBox", fps = 60, imageSuffix = { ["@2x"] = 1.5 }, },

@davebollinger: as of 2016.2994 (see my post from yesterday above), event.x returns fractions. I ran your example in 2016.2995 and got more or less the same result as with Rob’s code. Your counter shows that consecutively triggered “moved” phases do produce duplicate values for event.x.

that’s good news, a step in the right direction.

still, what you’d expect from a device of width “DW” would be DW unique values (fractional or not, depending on the ratio of content dimensions to device dimensions)

however, for content of width “CW”, there appears to be a flaw in the mapping from [0,DW) to [0,CW) because we’re only getting back CW unique values - that is, the range [0,DW) has been quantized to just CW unique values, somewhere apparently prior to being scaled by CW/DW.  perhaps some intermediate int value is used halfway through the calc that shouldn’t be? (wild guess)

@davebollinger: good analysis! You are absolutely right, the number of  unique values returned should be DW. Above, Rob says that corona is basically just relaying the values that the os gives. If so, it could be that the quantizing occurs outside of the reach of corona unless there is a way to modify the behavior of the os in this regard, I don’t know…

@Rob: could you please double check that corona does absolutely nothing with the values passed form the os? If so, could the “device based” coordinate values be extrated from the os in another way?

We scale the values based on your config.lua settings. If you define 320x480 an you’re on a 640x960 device, we will have to halve the values to map them to your 320x480 content area.

Rob

@Rob: as you can see in my config.lua (see previous posting) I now use a 640 x 960 resolution. Given the imageSuffix settings (see same posting), iPhone 6 does not need scaling. Therefore, content scaling cannot be the reason for this issue. More importantly, it does not explain the results that davebollinger points out in his postings  about quantization.

At this point since you have a reproducible test case, please file a bug report using Dave’s project.

Thanks

Rob