Hello everyone,
I'm a new coder who finished CS50 about a month ago, so I have some basics of programming, and have made pong and the basic mario-like game from the CS50 tutorials. Please tailor your advice accordingly.
I'm currently coding a game that is exclusively a mobile phone game. It will be using pixel art I'll have commissioned. I'd like it to be on Android and iOS. My control scheme exclusively consists of pressing buttons on the game's UI, so I'm not too worried about getting the controls to work on the phones. All the other game mechanics I have in my head shouldn't have to be altered for a different platform (so I hope haha).
What I am worried about is I have no idea if I should be planning for anything in my code for the game to work on Android/iOS. I have already read the topics on the wiki and forums regarding distribution. I have no problem spending the time working out how to get features to work, I just don't want to spend months making something and finding out it all has to be redone because I wasn't aware of something basic.
1. Conceptually, what are the issues regarding screen size, resolution, and having my art assets work with all that? If the game works on my laptop, will the art scale on the phone? Should I be testing everything from the start in a certain resolution on my laptop to emulate the phone screen? Are you aware of any good resources regarding these types of topics?
2. Is my code just going to work after I import it with the distribution tools? Are there certain features of love or Lua that I should avoid using because they aren't cross platform? Do phones work in some different way that I should structure how my code handles my game mechanics? Should I be skeptical of Lua's tables and getting creative with them? Is multi-threading at all a relevant consideration for a somewhat simple game?
3. Does running a (cloud) server change any considerations? Is this required to stop cheating from happening on a leaderboard system? Do I have to consider hackers altering in game values or does Android/iOS prevent this from happening? How are in-game real life money purchases handed normally? Any good resources on this as well is appreciated.
4. Is there any other category of a potential problem I'm not even aware of?
I've always wanted to make games, so thank you all for helping me out on my journey!
Mobile game considerations?
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
Re: Mobile game considerations?
Note that this post is my personal opinion.
You can make the assets big enough to look fine at the biggest resolution, and then reduce them. But in that case, test! Something that isn't very well known is that downscaling works by default up to 1/2 the original size. Past that you must activate mipmaps if you don't want your reduced images to look like crap.
Fonts should be handled separately, because they don't support mipmaps, but fortunately they are generated at multiple sizes with perfect resolution, as they are vector graphics, sort of.
Note that gestures won't work in desktop. If you want something that requires a gesture, you'll have to be prepared to make that available by some other mechanism in platforms that don't have touch screens. For example, a popup context menu could be enabled with both RMB and touching with two fingers.
There are two ways to stress the GC: to have lots of active objects, and to generate lots of garbage. The first means that the fewer tables you use, the better. For example, in case of 2D maps, it's better to flatten your map to 1D, than having 1 table with NROWS sub-tables each with a row.
The second means that you should avoid creating temporary variables that need cleaning up. For example, avoid things like this:
You could rewrite it like this:
Avoid creating functions on the fly; in most cases you don't need them to work as closures, or you can make non-closure versions. Keep them until they are really needed. For example, this is bad:
Instead, create the function outside the other function, making use of the `self` parameter, and add a reference to it in the object:
Relying exclusively on metatables for parent class access may not be a good idea, because that requires following the full chain of metatables for every call to a method on the base class. It's better to copy the methods from the parent class to the child in the constructor. Think of that as a cache of the parent methods in the child. That's not saying to avoid using metatables; just to do the copying additionally.
Good question with no easy answer.
Probably not. Phones usually have bigger resolutions than desktops. In that case, the graphics may look pixel-y or blurry. Or more rarely, it can be the other way around, if you have a large laptop screen and a phone with low resolution.
You can make the assets big enough to look fine at the biggest resolution, and then reduce them. But in that case, test! Something that isn't very well known is that downscaling works by default up to 1/2 the original size. Past that you must activate mipmaps if you don't want your reduced images to look like crap.
Fonts should be handled separately, because they don't support mipmaps, but fortunately they are generated at multiple sizes with perfect resolution, as they are vector graphics, sort of.
You should check in the actual phone from time to time. Preferably in several phones with different resolutions.
I am not. Maybe someone else.
Start by testing this. Make sure you can do it and that it works as you expect. And then hope for no changes having occurred by the time you want to release your final product (like the recent mandatory 64-bit change, or store policies or whatever).
There are two groups that I'm aware of: from phone to desktop, the ones that are typically phone-specific like touch events and accelerometer; from desktop to phone, the keyboard controls; these are hard to port. As far as I understand neither is a concern to you if your controls are basically going to consists of pressing UI buttons, so you can restrict yourself to using the mouse events.
Note that gestures won't work in desktop. If you want something that requires a gesture, you'll have to be prepared to make that available by some other mechanism in platforms that don't have touch screens. For example, a popup context menu could be enabled with both RMB and touching with two fingers.
I'd say the controls mark the big difference. But for the kind of controls you're planning on, not fundamentally. Maybe the kind of public for one platform or the other differs, but that's a "meta issue" not really related to Löve.
Lua has a problem. The garbage collector sucks. The more objects the GC needs to deal with, the slower it gets. For big projects, GC issues manifest themselves as lag spikes.
There are two ways to stress the GC: to have lots of active objects, and to generate lots of garbage. The first means that the fewer tables you use, the better. For example, in case of 2D maps, it's better to flatten your map to 1D, than having 1 table with NROWS sub-tables each with a row.
The second means that you should avoid creating temporary variables that need cleaning up. For example, avoid things like this:
Code: Select all
myFunc{param1 = 3, param2 = 5}
Code: Select all
local myTable = {} -- place this where it will be executed only once
...
-- every time you want to call, overwrite the current values:
myTable.param1 = 3
myTable.param2 = 5
myFunc(myTable)
Code: Select all
local function newObj()
local obj = {x = 0}
function obj:incX()
obj.x = obj.x + 1
end
return obj
end
Code: Select all
local function obj_incX(self)
self.x = self.x + 1
end
local function newObj()
local obj = {x = 0, incX = obj_incX}
return obj
end
Probably not.
I'll defer these questions to others.Kemair wrote: ↑Wed Jul 29, 2020 1:25 am 3. Does running a (cloud) server change any considerations? Is this required to stop cheating from happening on a leaderboard system? Do I have to consider hackers altering in game values or does Android/iOS prevent this from happening? How are in-game real life money purchases handed normally? Any good resources on this as well is appreciated.
I don't know of any.
- zorg
- Party member
- Posts: 3465
- Joined: Thu Dec 13, 2012 2:55 pm
- Location: Absurdistan, Hungary
- Contact:
Re: Mobile game considerations?
I'll keep my opinions on monetized mobile software to myself, so i'll just add a few relevant things instead:
Multi-threading depends on what kind of simple game you're making, however there might be one more consideration i'll touch upon a bit later.
Both ios and android platforms disable the JIT part of luaJIT, that löve uses; what this means for you is that you should/can not use some more advanced things, like the FFI library, along with the fact that things *might* be a bit slower at times... again, depending on game simplicity and how much you want to optimize things, this is probably a moot point, but alas, i thought to mention it.
Your 3rd point is a bit complex, so i'll take it one at a time.
Since you want a centralized leaderboard that can't be cheated, indeed values need to somehow be sent to a server (and then retrieved). For the netcode to not block, you might want to either use coroutines, or a separate thread; i don't know if the former's enough, but it might depend on the networking library you're using if that supports non-blocking calls or not. (iirc luasocket and enet both do, that are included with löve; no https/ssl support for now though, which is kind of needed, probably - especially for money stuff, unless the library dealing with this is secure itself...)
I know cheatengine exists for desktop, but idk if there are apps like that, or even if it's possible to alter memory, on mobile os-es. You should still safeguard the values sent to the server somehow though (e.g. with a hash or something, maybe queried through some process tied to the user's account that is needed to deal with IAP-s). Since you also mentioned in-app purchases, you'll probably need some external library to facilitate those calls; there's one that integrates admob into löve on the forums, but idk if that's relevant/useful for your use-case or not.
Multi-threading depends on what kind of simple game you're making, however there might be one more consideration i'll touch upon a bit later.
Both ios and android platforms disable the JIT part of luaJIT, that löve uses; what this means for you is that you should/can not use some more advanced things, like the FFI library, along with the fact that things *might* be a bit slower at times... again, depending on game simplicity and how much you want to optimize things, this is probably a moot point, but alas, i thought to mention it.
Your 3rd point is a bit complex, so i'll take it one at a time.
Since you want a centralized leaderboard that can't be cheated, indeed values need to somehow be sent to a server (and then retrieved). For the netcode to not block, you might want to either use coroutines, or a separate thread; i don't know if the former's enough, but it might depend on the networking library you're using if that supports non-blocking calls or not. (iirc luasocket and enet both do, that are included with löve; no https/ssl support for now though, which is kind of needed, probably - especially for money stuff, unless the library dealing with this is secure itself...)
I know cheatengine exists for desktop, but idk if there are apps like that, or even if it's possible to alter memory, on mobile os-es. You should still safeguard the values sent to the server somehow though (e.g. with a hash or something, maybe queried through some process tied to the user's account that is needed to deal with IAP-s). Since you also mentioned in-app purchases, you'll probably need some external library to facilitate those calls; there's one that integrates admob into löve on the forums, but idk if that's relevant/useful for your use-case or not.
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Re: Mobile game considerations?
I don't think that's correct, at least for Android. FFI runs just fine with the JIT off. There's even an FFI library for PUC Lua almost compatible with LuaJIT's.
For iOS, I'm not sure. I know that the JIT is disabled due to Apple's restrictive policies; I'm not sure if FFI is as well.
The JIT is disabled on Android for now, but that will change soon. https://love2d.org/forums/viewtopic.php ... 79#p234179
Re: Mobile game considerations?
Touchscreen input is probably the biggest difference between desktop and mobile gaming.
Your controls may work, but that's not enough the question should be "is the game fun to play on a tiny touchscreen".
That's why it's good to look into gestures and multitouch input.
As for dealing with hackers and cheating, I doubt that will be an issue unless your game is already very popular.
Re: Mobile game considerations?
Thank you everyone for the replies! Currently have a lot going so it took some time to get back to this post.
Can I flag a table for deletion by the GC as such?:
Thanks again everyone!
I'm not sure I understand the difference here with the code. Are you saying I should minimize the amount of tables I use by writing over values in a single table instead of creating separate tables? What about nested tables in a single table, is this better?pgimeno wrote: ↑Wed Jul 29, 2020 11:43 am
Lua has a problem. The garbage collector sucks. The more objects the GC needs to deal with, the slower it gets. For big projects, GC issues manifest themselves as lag spikes.
There are two ways to stress the GC: to have lots of active objects, and to generate lots of garbage. The first means that the fewer tables you use, the better. For example, in case of 2D maps, it's better to flatten your map to 1D, than having 1 table with NROWS sub-tables each with a row.
The second means that you should avoid creating temporary variables that need cleaning up. For example, avoid things like this:You could rewrite it like this:Code: Select all
myFunc{param1 = 3, param2 = 5}
Code: Select all
local myTable = {} -- place this where it will be executed only once ... -- every time you want to call, overwrite the current values: myTable.param1 = 3 myTable.param2 = 5 myFunc(myTable)
Can I flag a table for deletion by the GC as such?:
Code: Select all
local myTable = {}
myTable.param1 = 3
myTable.param2 = 5
...
myTable = nil
I intuitively understand what passing 'self' to a function does. Can you explain what it does on the code and performance level? Is it just passing values by reference to the function so it can access the variables? Does this pass local variables as well?pgimeno wrote: ↑Wed Jul 29, 2020 11:43 am Avoid creating functions on the fly; in most cases you don't need them to work as closures, or you can make non-closure versions. Keep them until they are really needed. For example, this is bad:Instead, create the function outside the other function, making use of the `self` parameter, and add a reference to it in the object:Code: Select all
local function newObj() local obj = {x = 0} function obj:incX() obj.x = obj.x + 1 end return obj end
Code: Select all
local function obj_incX(self) self.x = self.x + 1 end local function newObj() local obj = {x = 0, incX = obj_incX} return obj end
Thank you for your response zorg, I don't have any questions. In terms of monetization I'm looking to keep things as ethical as possible, avoiding pay to win, and keeping paid advantages mostly outside my core game loop. To be able to continue making fun games I do need some amount back in profit, but fun is my main objective here!
I'm more worried about building things (like art assets), and finding out later that they are completely unusable and having to have them redone. The genre I have in mind has a low reliance on inputs from the player, so tweaking them doesn't radically change other parts of the code or design (generally). I'm also fully ready to tweak things for polish (and will probably add some gestures as this could be a good idea!), just really looking for general red flags that a noobie has no idea they are walking into.ivan wrote: ↑Fri Jul 31, 2020 6:29 amTouchscreen input is probably the biggest difference between desktop and mobile gaming.
Your controls may work, but that's not enough the question should be "is the game fun to play on a tiny touchscreen".
That's why it's good to look into gestures and multitouch input.
As for dealing with hackers and cheating, I doubt that will be an issue unless your game is already very popular.
Thanks again everyone!
Re: Mobile game considerations?
When you can afford to do that, it's better. This is not always the case.Kemair wrote: ↑Mon Aug 24, 2020 1:46 pmI'm not sure I understand the difference here with the code. Are you saying I should minimize the amount of tables I use by writing over values in a single table instead of creating separate tables? What about nested tables in a single table, is this better?pgimeno wrote: ↑Wed Jul 29, 2020 11:43 am The second means that you should avoid creating temporary variables that need cleaning up. For example, avoid things like this:You could rewrite it like this:Code: Select all
myFunc{param1 = 3, param2 = 5}
Code: Select all
local myTable = {} -- place this where it will be executed only once ... -- every time you want to call, overwrite the current values: myTable.param1 = 3 myTable.param2 = 5 myFunc(myTable)
Every time you write a table constructor { ... }, a new object needs to be allocated. If this object is temporary, like for passing arguments to a function, it's an object that needs to be created and destroyed for no good. Best to avoid creating interfaces that rely on parameters that come in tables. That is, try to avoid creating interfaces like that of love.window.setMode, for example, although in this specific case it's harmless because it runs very few times per program (in most cases 0 to 1 times). And if you can't avoid it, try to reuse a table as I indicated.
Consider also that it's almost always faster to clear a table used as an array, than to rewrite the variable with a new fresh table.
Yes. And that gives work to the GC, which is what you need to avoid if possible.Kemair wrote: ↑Mon Aug 24, 2020 1:46 pm Can I flag a table for deletion by the GC as such?:Code: Select all
local myTable = {} myTable.param1 = 3 myTable.param2 = 5 ... myTable = nil
OK, not sure if you understand colon syntax. If not, I give a quick intro here: https://love2d.org/forums/viewtopic.php ... 94#p223194 or here: https://love2d.org/forums/viewtopic.php ... 70#p227470
So, this code:
Code: Select all
local function newObj()
local obj = {x = 0}
function obj:incX()
obj.x = obj.x + 1
end
return obj
end
Code: Select all
local function newObj()
local obj = {x = 0}
obj.incX = function (self)
obj.x = obj.x + 1
end
return obj
end
Colon syntax means that these two function calls are equivalent:
Code: Select all
obj:incX()
obj.incX(obj)
You could almost say that tables are passed by reference, yes. It's not exactly how passing by reference works in languages that support that, though. It's more like passing by value a pointer to the table. If you alter the pointer inside the function, for example, to point to another table, the caller does not get a modified value (in real passing by reference it would). But if you alter the object pointed to, every variable pointing to it will see the change.
Hope this clarifies it:
Code: Select all
local A = {a = 1}
local B = {b = 1}
local C = A
local function f1(param)
param = B -- this does not change anything in the caller; a real pass-by-reference would
end
local function f2(param)
param.a = 5 -- this alters the table passed to the function
end
print(A) -- prints some value X
print(B) -- prints some value Y
f1(A)
print(A) -- prints the value X, NOT the value Y
f2(A)
print(C.a) -- prints 5
Who is online
Users browsing this forum: Ahrefs [Bot], whateverest and 5 guests