Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!). https://deluxepixel.com
btw, you should code your games so that joysticks are detected then turn off any on-screen controls. If you get a touch event then turn them back on, off again when you get a joystick button press, etc.
This is because there are tablets / phones out there with joysticks built in or connected via bluetooth.
imho every game should try support joysticks and keyboard, it also makes it easier to make a version for pc, mac, xbox, etc...
joysticks are supported by every type of export, including html5, you just have to include the controller plugin. I made a joystick controller 'demo' that's included with Gideros if you need an example.
Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!). https://deluxepixel.com
@SinisterSoft , on my TCL Android TV actually device[5] is nil as all other device[i] for (i=1..5). application:getDeviceInfo() returns "Android". so in this case how to notice that it's a tv? EDIT: it works now, i did not notice the {} around application:getDeviceInfo().
for 'back' button event.keyCode=4 for me after testing, i don't know if this has a name in gideros. for 'ok' button i think it was 96, again i'm not sure if it has a name.
These are some snips of unified joystick and keyboard controls being made into a bitpattern that the rest of the game uses. It makes it easy to support both keyboard or joystick or anything else you need to insert into the bitpattern.
The bitpattern is:
YZrlABUDLR where R is bit 0. (U is up, D is down, L is left and R is right, the others are buttons).
KeyCode.BUTTON_BACK is used for checking if the button is the back button.
My code that inserts bits/removes bits...
function controllerDown(p,k,i)
touchScreen=false
idleCounter=0if k==KeyCode.BUTTON_A or k==KeyCode.BUTTON_Y or k==buttonA or k==KeyCode.BUTTON_MENU then p.padRGUDLR=p.padRGUDLR|0b100000
elseif k==KeyCode.BUTTON_B or k==KeyCode.BUTTON_X or k==KeyCode.U or k==buttonB then p.padRGUDLR=p.padRGUDLR|0b010000
elseif k==KeyCode.DPAD_UP then p.padRGUDLR=p.padRGUDLR|0b001000
elseif k==KeyCode.DPAD_DOWN then p.padRGUDLR=p.padRGUDLR|0b000100
elseif k==KeyCode.DPAD_LEFT then p.padRGUDLR=p.padRGUDLR|0b000010
elseif k==KeyCode.DPAD_RIGHT then p.padRGUDLR=p.padRGUDLR|0b000001
elseif k==KeyCode.BUTTON_L1 then p.padRGUDLR=p.padRGUDLR|0b10000000
elseif k==KeyCode.BUTTON_R1 then p.padRGUDLR=p.padRGUDLR|0b01000000
elseif k==KeyCode.Y then p.padRGUDLR=p.padRGUDLR|0b1000000000 -- or k==KeyCode.BUTTON_L2elseif k==KeyCode.Z then p.padRGUDLR=p.padRGUDLR|0b0100000000
--elseif k==KeyCode.BUTTON_R2 then setPause()elseif k==KeyCode.BUTTON_BACK then back=trueelseprint("Button Down ", i, k, findKeyCode(k))endif p.padRGUDLR~=0then p.joypad=trueendendfunction controllerUp(p,k,i)
touchScreen=false
idleCounter=0if k==KeyCode.BUTTON_A or k==KeyCode.BUTTON_Y or k==buttonA or k==KeyCode.BUTTON_MENU then p.padRGUDLR=p.padRGUDLR&0b1111011111
elseif k==KeyCode.BUTTON_B or k==KeyCode.BUTTON_X or k==KeyCode.U or k==buttonB then p.padRGUDLR=p.padRGUDLR&0b1111101111
elseif k==KeyCode.DPAD_UP then p.padRGUDLR=p.padRGUDLR&0b1111110111
elseif k==KeyCode.DPAD_DOWN then p.padRGUDLR=p.padRGUDLR&0b1111111011
elseif k==KeyCode.DPAD_LEFT then p.padRGUDLR=p.padRGUDLR&0b1111111101
elseif k==KeyCode.DPAD_RIGHT then p.padRGUDLR=p.padRGUDLR&0b1111111110
elseif k==KeyCode.BUTTON_L1 then p.padRGUDLR=p.padRGUDLR&0b1101111111
elseif k==KeyCode.BUTTON_R1 then p.padRGUDLR=p.padRGUDLR&0b1110111111
elseif k==KeyCode.Y then p.padRGUDLR=p.padRGUDLR&0b0111111111 -- or k==KeyCode.BUTTON_L2elseif k==KeyCode.Z then p.padRGUDLR=p.padRGUDLR&0b1011111111
elseprint("Button Up ", i, k, findKeyCode(k))endend
My code that calls the above two routines for controllers - I do it this way so if I want I can feed in joypad moves pretty easily from other routines, you will have to modify it to work in your case as I have other code that checks for controller removal, priorities, etc But it should get you 'there'...
controller:addEventListener(Event.KEY_DOWN, function(e)-- print("Button Down ", e.keyCode, findKeyCode(e.keyCode))local id,id2=0,e.playerId
for loop=1,#controllerMap doif id2==controllerMap[loop]then
id=loop
breakendendif id>=1and id<=#players then
controllerDown(players[id],e.keyCode,id)elseif find(lower(controller:getControllerName(e.playerId)),"remote")~=nilthen
controllerDown(players[1],e.keyCode,0)endendend)
controller:addEventListener(Event.KEY_UP, function(e)local id,id2=0,e.playerId
for loop=1,#controllerMap doif id2==controllerMap[loop]then
id=loop
breakendendif id>=1and id
This is the keyboard routine that listens for the keys and modifies the bits:
stage:addEventListener(Event.KEY_DOWN,function(e)
idleCounter=0local p=players[2]--print("Button Down ", id, e.keyCode, e.realCode)local k=e.keyCode
local beep=falseif k==KeyCode.BACK or k==KeyCode.ESC then back=trueelseif k==KeyCode.SPACE or k==KeyCode.CENTER or e.realCode==buttonA then p.padRGUDLR=p.padRGUDLR|0b100000 touchScreen=falseelseif k==KeyCode.ENTER or e.realCode==buttonB then p.padRGUDLR=p.padRGUDLR|0b010000 touchScreen=falseelseif k==KeyCode.UP then p.padRGUDLR=p.padRGUDLR|0b001000 touchScreen=falseelseif k==KeyCode.DOWN then p.padRGUDLR=p.padRGUDLR|0b000100 touchScreen=falseelseif k==KeyCode.LEFT then p.padRGUDLR=p.padRGUDLR|0b000010 touchScreen=falseelseif k==KeyCode.RIGHT then p.padRGUDLR=p.padRGUDLR|0b000001 touchScreen=falseelseif k==KeyCode.R andnot recordMode then recordMode=true sfx[15].play=trueelseif k==KeyCode.NUM_1 then saveRecording(1)elseif k==KeyCode.NUM_2 then saveRecording(2)elseif k==KeyCode.L then
levelSkip=trueelseif k==KeyCode.Q then
gameQuit=trueend--if not optionsMode then--if k==KeyCode.P then setPause() end-- if not pause then-- if k==KeyCode.F then if setView(0) then beep=true end-- elseif k==KeyCode.A then if setView(1) then beep=true end-- elseif k==KeyCode.L then if setView(2) then beep=true end-- elseif k==KeyCode.G then setGalacticChart()-- elseif k==KeyCode.H then setHyperwarp()-- elseif k==KeyCode.S then setShields()--elseif k==KeyCode.B then megaBomb()--elseif k==KeyCode.T then setTracking()-- elseif k==KeyCode.C then setComputer()--elseif k==KeyCode.M then setTarget()-- elseif k==KeyCode.NUM_0 then setVelocity(0)-- elseif k==KeyCode.NUM_1 then setVelocity(1)-- elseif k==KeyCode.NUM_2 then setVelocity(2)-- elseif k==KeyCode.NUM_3 then setVelocity(3)-- elseif k==KeyCode.NUM_4 then setVelocity(4)-- elseif k==KeyCode.NUM_5 then setVelocity(5)-- elseif k==KeyCode.NUM_6 then setVelocity(6)-- elseif k==KeyCode.NUM_7 then setVelocity(7)-- elseif k==KeyCode.NUM_8 then setVelocity(8)-- elseif k==KeyCode.NUM_9 then setVelocity(9)-- end-- end--end--if beep then sfx[1].play=true endend)
stage:addEventListener(Event.KEY_UP,function(e)local p=players[2]local k=e.keyCode
--elseif k==KeyCode.F and pc then--if fullScreen then fullScreen=false else fullScreen=true end--application:setFullScreen(fullScreen) if k==KeyCode.SPACE or k==KeyCode.CENTER or e.realCode==buttonA then p.padRGUDLR=p.padRGUDLR&0b1111011111 touchScreen=falseelseif k==KeyCode.ENTER or e.realCode==buttonB then p.padRGUDLR=p.padRGUDLR&0b1111101111 touchScreen=falseelseif k==KeyCode.UP then p.padRGUDLR=p.padRGUDLR&0b1111110111 touchScreen=falseelseif k==KeyCode.DOWN then p.padRGUDLR=p.padRGUDLR&0b1111111011 touchScreen=falseelseif k==KeyCode.LEFT then p.padRGUDLR=p.padRGUDLR&0b1111111101 touchScreen=falseelseif k==KeyCode.RIGHT then p.padRGUDLR=p.padRGUDLR&0b1111111110 touchScreen=falseendend)
Then in my main loop, because it's a bit pattern I can do debounce of all the joypad movement pretty easily in one go:
You use padDbRGUDLR to see what buttons have just been pressed (not over a sustained period). Handy for up/down menus, non-repeating fire buttons, jumping, etc
The bitpattern and the debounce method are things I've been doing ever since the mid 80s - but then in assembly code. In enemy 'brains' I sometimes make them generate the same bit patterns - these are then fed into the movement for the enemy. That way, a second player can 'take over' any of the enemies or you can use it for debugging how enemies should move.
In the code you will also see touchscreen=false. This flags the game to remove any on screen touchscreen buttons. If the screen is touched then it sets the flag and puts the buttons back. The games start with touchscreen set to false.
Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!). https://deluxepixel.com
what i did not manage to do is to publish my app on the developer console to android tvs. by searching it seems this should be done in the pricing page but for a free app i do not see there anything that could do that. so if you know what i miss, let me know.
what i did not manage to do is to publish my app on the developer console to android tvs. by searching it seems this should be done in the pricing page but for a free app i do not see there anything that could do that. so if you know what i miss, let me know.
I don't think there is a specific Android TV pricing, but maybe you need to enable TV compat in the manifest, in 'require' plugin
"Before you can publish to Android TV users, you need to opt-in to Android TV from the Pricing and Distribution section of the Play Console. Opt-in means that you want your app to be made available to Android TV users through Google Play, and that your app meets the TV app quality guidelines. "
however at the app pricing part of the developer console what i see is only this: "Your app is available for free on Google Play, and can't be changed to paid"
Strange, I don't remember having to do anything in the 'pricing' section of the store (my app is free). Uploading TV assets (screenshots, banner) on the store page was enough
You need to add the require plugin and tick all the relevant tv options:
Untick things you don't think should be mandatory - eg gps on a TV.
Then upload the game to the play store. After that you will see the TV options available. At least that's the way it works for me.
Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!). https://deluxepixel.com
You also go through the TV approval service, they approve it differently than a normal app - there are slightly more rules to follow.
Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!). https://deluxepixel.com
for most tv devices in device catalog it is written "Not opted in" for me, that's what i want to change. (there are some for which "Supported" is written).
i've asked support and they quickly told me the secret recipe i missed:
"Kindly follow steps below on how to include your app to Android TV : Access the Play Console and select the app. Go to “Release” > "Setup" > "Advanced settings" Go to the "Release types" tab. (If you need to optimize the app for Android TV, Play Console will show the requirements.)"
now that this is done they rejected due to this: "No full-size app banner Your app does not contain a full-size app banner or is it not visible in the launcher. We are targeting 1080P, which we consider xhdpi. Apps should include the banner in the xhdpi (320 dpi) drawables folder with a size of (320px × 180px). Please refer to our Home Screen Banner and UI Patterns documentation."
and indeed, even though i added a tv banner in gideros to my app it does not put it into the xhdpi folder, this probably should be corrected in next gideros version.
i thought to correct this issue by simply copying the banner in that folder too but then the aab cannot be uploaded anymore: "Your Android App Bundle has an invalid signature. Upload again with a valid signature." i guess there is some checksum or something preventing this, so really gideros itself should package the aab in a correct way. or is there some simple workaround meanwhile? thanks
thanks, i've added it and resubmitted, let's see. in fact they have noted another issue which i've not corrected:
"The title should help users identify apps in the launcher. Please refer to our Visual Design and User Interaction documentation for more information. For example, your app title is not visible on the banner"
but i hope this won't be a dealbreaker, i prefer my banner without the text.
You need to appeal - let them know where the banner is - the manifest tells them. Whoever refused it didn't look at the manifest, they just assumed it would be in that folder.
Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!). https://deluxepixel.com
@SinisterSoft , good idea, although i hate to argue with these reviewers. yet i've resubmitted already, so next time. perhaps they will still have issue with having no name in the banner even though many other apps are like this.
I had this happen to me before - you do need the name, and the appeal about where the image is does work. It gets raised to someone higher. The person who looked at yours will be new or lazy.
Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!). https://deluxepixel.com
Comments
https://stackoverflow.com/questions/27138838/how-can-i-check-if-an-app-is-running-on-an-android-tv
Then you can use the native bridge to call some android native functions from LUA side
Likes: MoKaLux
Likes: keszegh, MoKaLux, vitalitymobile
https://deluxepixel.com
This is because there are tablets / phones out there with joysticks built in or connected via bluetooth.
imho every game should try support joysticks and keyboard, it also makes it easier to make a version for pc, mac, xbox, etc...
joysticks are supported by every type of export, including html5, you just have to include the controller plugin. I made a joystick controller 'demo' that's included with Gideros if you need an example.
Likes: keszegh, MoKaLux
https://deluxepixel.com
Likes: MoKaLux, SinisterSoft
Fragmenter - animated loop machine and IKONOMIKON - the memory game
Fragmenter - animated loop machine and IKONOMIKON - the memory game
EDIT:
it works now, i did not notice the {} around application:getDeviceInfo().
for 'back' button event.keyCode=4 for me after testing, i don't know if this has a name in gideros. for 'ok' button i think it was 96, again i'm not sure if it has a name.
Fragmenter - animated loop machine and IKONOMIKON - the memory game
The bitpattern is:
YZrlABUDLR where R is bit 0. (U is up, D is down, L is left and R is right, the others are buttons).
KeyCode.BUTTON_BACK is used for checking if the button is the back button.
My code that inserts bits/removes bits...
The bitpattern and the debounce method are things I've been doing ever since the mid 80s - but then in assembly code. In enemy 'brains' I sometimes make them generate the same bit patterns - these are then fed into the movement for the enemy. That way, a second player can 'take over' any of the enemies or you can use it for debugging how enemies should move.
In the code you will also see touchscreen=false. This flags the game to remove any on screen touchscreen buttons. If the screen is touched then it sets the flag and puts the buttons back. The games start with touchscreen set to false.
https://deluxepixel.com
https://play.google.com/store/apps/details?id=com.longtitle.macimaze
what i did not manage to do is to publish my app on the developer console to android tvs. by searching it seems this should be done in the pricing page but for a free app i do not see there anything that could do that. so if you know what i miss, let me know.
Fragmenter - animated loop machine and IKONOMIKON - the memory game
i refer to https://developer.android.com/distribute/best-practices/launch/distribute-tv
in particular:
"Before you can publish to Android TV users, you need to opt-in to Android TV from the Pricing and Distribution section of the Play Console. Opt-in means that you want your app to be made available to Android TV users through Google Play, and that your app meets the TV app quality guidelines. "
however at the app pricing part of the developer console what i see is only this:
"Your app is available for free on Google Play, and can't be changed to paid"
Fragmenter - animated loop machine and IKONOMIKON - the memory game
Fragmenter - animated loop machine and IKONOMIKON - the memory game
Fragmenter - animated loop machine and IKONOMIKON - the memory game
Untick things you don't think should be mandatory - eg gps on a TV.
Then upload the game to the play store. After that you will see the TV options available. At least that's the way it works for me.
https://deluxepixel.com
https://deluxepixel.com
Fragmenter - animated loop machine and IKONOMIKON - the memory game
Fragmenter - animated loop machine and IKONOMIKON - the memory game
"Kindly follow steps below on how to include your app to Android TV :
Access the Play Console and select the app.
Go to “Release” > "Setup" > "Advanced settings"
Go to the "Release types" tab. (If you need to optimize the app for Android TV, Play Console will show the requirements.)"
Fragmenter - animated loop machine and IKONOMIKON - the memory game
"No full-size app banner
Your app does not contain a full-size app banner or is it not visible in the launcher. We are targeting 1080P, which we consider xhdpi. Apps should include the banner in the xhdpi (320 dpi) drawables folder with a size of (320px × 180px). Please refer to our Home Screen Banner and UI Patterns documentation."
and indeed, even though i added a tv banner in gideros to my app it does not put it into the xhdpi folder, this probably should be corrected in next gideros version.
Fragmenter - animated loop machine and IKONOMIKON - the memory game
"Your Android App Bundle has an invalid signature. Upload again with a valid signature."
i guess there is some checksum or something preventing this, so really gideros itself should package the aab in a correct way.
or is there some simple workaround meanwhile? thanks
Fragmenter - animated loop machine and IKONOMIKON - the memory game
in fact they have noted another issue which i've not corrected:
"The title should help users identify apps in the launcher. Please refer to our Visual Design and User Interaction documentation for more information.
For example, your app title is not visible on the banner"
but i hope this won't be a dealbreaker, i prefer my banner without the text.
Fragmenter - animated loop machine and IKONOMIKON - the memory game
https://deluxepixel.com
perhaps they will still have issue with having no name in the banner even though many other apps are like this.
Fragmenter - animated loop machine and IKONOMIKON - the memory game
https://deluxepixel.com
Fragmenter - animated loop machine and IKONOMIKON - the memory game