I was happy using arc4random_uniform since iOS, and also for iOS targets of cocos2d-x.
Turns out it doesn't work for Android. The error:
error: 'arc4random_uniform' was not declared in this scope
How can I get around this?
Worst case, at compile time I'd check if arc4random_uniform() exists, and if not, use some other method (like the old arc4random()...).
I really would like to avoid using different code bases for different targets here.
Any other suggestions?
Note: As cocos2d-x is a "one code"→"many platforms", delegating this issue to Java code for Android would work against that.
Some of the C++ libs you can use in ios are not available in Android.
Unfortunately arc4ramndom is just one of them.
So the only way is to use an alternative of the stdlib like std::rand() or the default random engine if you want something more.
This is an example about how to use std::default_random_engine to get a random value in a given interval.
int randomValue(int from, int to) {
std::random_device rd;
std::default_random_engine e1(rd());
std::uniform_int_distribution<int> uniform_dist(from, to);
int mean = uniform_dist(e1);
return mean;
}
You can use Cocos2d native methods for generating random numbers. CCRANDOM_0_1() for example generates a random CGFloat between 0 and 1.
Related
In Typescript (or JavaScript) I always try to write in a way that if I (or another developer) has to touch my code in one year, it is really easy to understand what is happening. So I do not try to find the shortest code possible but the clearer one.
I do not worry about the size of the file because I know in production this function:
function myFunction(value: number) {
if(otherFunction(number){
return true;
}
if(yetAtherFunction(number){
return true;
}
return false;
}
will be converted to this:
function myFunction(n){return!!otherFunction(n)||!!yetAtherFunction(n)}
Would something similar happens with kotlin?
I ask because I offen find this kind of code:
val myDrawable = item?.image?.let { Uri.parse(it.toString()) } ?: R.drawable.my_default_image
and to me it is not easy to do a fast parse to know what is happening why doing a PR or similar.
If I write that in a more verbose way, would it have an impact on the size of the final apk ?
Important:
To clarify, I am not asking is it better to write in this or that way? I am asking if the compiler tries to optimize the input like a typescript/javascript minifier does.
In Kotlin / Java world, all code must get compiled into bytecode before it can run anywhere, and in general this is basically an incredibly optimized binary blob where whitespace doesn't exist.
In interpreted languages like JS, the client / browser downloads a copy of the source and runs the source directly. Minifying is super important in these cases because it reduces the size of the file clients need to download by removing logically redundant characters. In TS, most clients cannot run it directly, so it instead gets transpiled into JS, and that is what is typically served to browsers / clients. (Some exceptions like Deno exist for example, which has a native ts interpreter).
The reason you see inlined code stuffed into one line, is purely for cosmetic / code style purposes.
Additional whitespace and variable names generally have no impact on the size / performance of your compiled Android app, so you can simply write code in the way that seems most presentable to you.
The server has more than 3000 models and each of them has several colors of material. I need to load separately models and textures and set textures depending on the user's choice. How to change baseColorMap, normalMap, metallicMap, roughnessMap in runtime?
after
modelRenderable.getMaterial().setTexture("normalMap", normalMap.get());
nothing happens
I'm doing something wrong. There is no information in documentation for that.
thank you for posting this question.
setTexture() appears to not work: Unfortunately this part of our API is still a little rough; it works but is very easy to get wrong. We're working on a sample to illustrate how to modify material parameters (including textures) at runtime and will improve our error reporting in the next release.
Thousands of models w/ multiple permutations how?: The plan here has two parts:
The binaries used by the Android Studio plugin will be made available for use in build scripts on server platforms. This will allow you to do a server-side conversion of your assets to .sfb. We'll be releasing a blog post soon on how to do this.
The .sfa will get the ability to contain loose textures and materials not explicitly associated with geometry, and .sfa's will be able to declare data dependencies on other .sfa's. This will mean that you can author (and deliver) .sfb's that contain textures/materials (but no geometry) and .sfb's that contain geometry (but no textures/materials), and if they're both available at instantiation time it will just work.
use this code`
CompletableFuture<Texture> futureTexture = Texture.builder()
.setSource(this, R.drawable.shoes)
.build();
and replace with
/*.thenAccept(renderable -> andyRenderable = renderable)*/
.thenAcceptBoth(futureTexture, (renderable, texture) -> {
andyRenderable = renderable;
andyRenderable.getMaterial().setTexture("baseColor", texture);
})
would work.
I've successfully written a go mobile library and used it from an Android Java app.
I've also successfully called a c function from JNI. This one has the JNIEnv pointer.
I'd like to pass the context/JNIEnv from Java to Go.
Here's where it seems to get complicated:
Go Mobile does not seem to use JNIEnv at all.
LoadJNI.java does have a context object and claims to pass it to the Go side. But there it isn't visible.
I've been able to include jni.h using the "C" directive
I can transfer the JNIEnv from JNI/C or store it there as a global variable but that's an ugly kludge.
https://github.com/golang/go/issues/16876 talks about a proposal to do reverse binding but it's unclear what the status is.
https://godoc.org/golang.org/x/mobile/cmd/gobind also talks about it but the following code snippet
import "Java/java/lang/System"
t := System.CurrentTimeMillis()
returns
cannot find package "Java/java/lang/System" in any of:
/usr/local/go/src/Java/java/lang/System (from $GOROOT)
/Users/----/go/src/Java/java/lang/System (from $GOPATH)
In C I solved it with a compiler directive: #cgo CFLAGS: -I...
But I'm not sure how to do it for Java
In short, I'm now stuck and would appreciate help. Ideally, I'd just like to pass the object as a parameter, if possible. However, I'd settle for any reverse binding to call Java from Go.
I hate to answer my own question, but I'd hate someone to go through this as well too. I'll update this answer as I go along.
Basic Setup
Edit build.gradle and add GOPATH and GO to gobind (additions in bold):
gobind {
pkg = ".../reverse/reverse"
GOPATH = "/Users/johndoe/go"
GO = "/usr/local/go/bin"
}
How to develop
Start from the reverse example. Get it to compile and run.
Make one modification and recompile.
Missing gobind
It turns out the installation process neglected to build gobind. Run go install golang.org/x/mobile/cmd/gobind
I'm Stuck
Trying to modify the reverse project to do anything other than what it's already doing is failing. Even stuff like passing an object and calling toString will fail.
More to come...
I look at Android source code
https://android.googlesource.com/platform/libcore/+/cff1616/luni/src/main/java/java/util/Arrays.java#1742
I realize Android's Arrays contains a public static method named checkStartAndEnd, which is not found in Java standard SE.
However, when I type java.util.Arrays.checkStartAndEnd in Android Studio, or look at the documentation https://developer.android.com/reference/java/util/Arrays.html, I realize checkStartAndEnd isn't valid for Android's Arrays class.
May I know why is it so? Am I looking at wrong Android source code?
You cannot see / use it because it's hidden (check the #hide tag in the Javadoc). If you compare the Android Arrays class with the Java SE one, you'll see that this checkStartAndEnd basically equals to rangeCheck, which is a private method there as well. As to why did they rename it? I have no idea, maybe some licensing issue or something else.
I'm trying to do the impossible and it doesn't seem to be working. The overall goal is this: I have a Component interface and I would like to show the user a list of classes on the classpath that implement that interface. The trick is, it has to run in Android.
Near as I can tell this is impossible to do at run time. The java mechanism (ServiceLoader) has been intentionally crippled by the Android toolchain, so it doesn't work. Guava doesn't work on Android, nor does ClassUtils, nor does Reflections.
At this point I've been yak shaving for 8 hours strait and there's no end in sight, so I'm looking for alternative approaches. My current thinking is to build a plugin (very much like sbt-spi, but not, because Android hates SPI) that can generate a text file at compile time that lists every class which implements the interface, so that at runtime I can open that file as a resource and then use reflection to start building them. Is that a reasonable idea? How should I go about it? (my current approach is "read the sbt-spi plugin source and try to copy it", but this seems like a scenario where "ask for wisdom" is a better approach)
Got it! I ended up using sbt-spi after all (huzzah not reinventing any wheels!) and just moving the output into the intermediate assets directory as part of the resourceGenerators task:
lazy val androidEntryPoint = (project in file("android-entry-point"))
.dependsOn(core, components, androidComponents)
.enablePlugins(SpiPlugin)
.settings(commonSettings: _*)
.settings(resourceGenerators in Compile += Def.task{
// This task copies the list of Components to the appropriate place to ensure
// it gets included in an accessible place in the APK
val res = collectResources.value._1 // item _1 here is for assets, item _2 is for resources. See the output of sbt "show androidEntryPoint/android:collectResources"
mapExport.value.toSeq.map { name =>
IO.move(target.value / name, res / name)
res / name
}
}.taskValue
)
That said, I'd love to hear a better approach if you can think of one. If none turn up in the next week or so I'll mark this one the answer.