jMonkeyEngine - how to get a body part which was colliding - character

I am making a game in jMonkeyEngine where 2 characters fight together. I want that program to fetch information about collisions with simple body parts. Example, if I give punch for a character the program has knowledge about the body part. I know that jMonkey can give me information about skeleton, but collisions are between geometries. My idea is to create a group of the objects as a character and get geometry in jME. Is it a good idea? I create objects in Blender.

You can try approximate your shapes with a geometry that is simpler and use that for collisions. For a character it works for me to use a cylinder and the helper class BetterCharacterControl.
private BetterCharacterControl characterControl;
#Override
public void simpleUpdate(float tpf) {
characterControl.setGravity(planetAppState.getGravity());
// Get current forward and left vectors of model by using its rotation
// to rotate the unit vectors
Vector3f modelForwardDir = characterNode.getWorldRotation().mult(Vector3f.UNIT_Z);
Vector3f modelLeftDir = characterNode.getWorldRotation().mult(Vector3f.UNIT_X);
// WalkDirection is global!
// You *can* make your character fly with this.
walkDirection.set(0, 0, 0);
if (leftStrafe) {
walkDirection.addLocal(modelLeftDir.mult(5));
} else if (rightStrafe) {
walkDirection.addLocal(modelLeftDir.negate().multLocal(5));
}
if (forward) {
walkDirection.addLocal(modelForwardDir.mult(5));
} else if (backward) {
walkDirection.addLocal(modelForwardDir.negate().multLocal(5));
}
characterControl.setWalkDirection(walkDirection);
// ViewDirection is local to characters physics system!
// The final world rotation depends on the gravity and on the state of
// setApplyPhysicsLocal()
if (leftRotate) {
Quaternion rotateL = new Quaternion().fromAngleAxis(FastMath.PI * tpf, Vector3f.UNIT_Y);
rotateL.multLocal(viewDirection);
} else if (rightRotate) {
Quaternion rotateR = new Quaternion().fromAngleAxis(-FastMath.PI * tpf, Vector3f.UNIT_Y);
rotateR.multLocal(viewDirection);
}
characterControl.setViewDirection(viewDirection);
if (walkDirection.length() == 0) {
if (!"Idle".equals(animationChannel.getAnimationName())) {
animationChannel.setAnim("Idle", 1f);
}
} else {
if (!"Walk".equals(animationChannel.getAnimationName())) {
animationChannel.setAnim("Walk", 0.7f);
}
}
}
You can use a collisionshape
private CylinderCollisionShape shape;
And use jme3's helper classes to get the collision data
CollisionResults results = new CollisionResults();
// System.out.println("1 #Collisions between" + ufoNode.getName()
// + " and " + jumpgateSpatial.getName() + ": " + results.size());
ufoNode.collideWith((BoundingBox) jumpgateSpatial.getWorldBound(),
results);
// System.out.println("2 #Collisions between" + ufoNode.getName()
// + " and " + jumpgateSpatial.getName() + ": " + results.size());
CollisionResults results2 = new CollisionResults();
// Use the results
if (results.size() > 0 && playtime > 50000) {
System.out.println("playtime" + playtime);
System.out.println("#Collisions between" + ufoNode.getName()
+ " and " + jumpgateSpatial.getName() + ": "
+ results.size());
// how to react when a collision was detected
CollisionResult closest = results.getClosestCollision();
System.out.println("What was hit? "
+ closest.getGeometry().getName());
System.out
.println("Where was it hit? " + closest.getContactPoint());
System.out.println("Distance? " + closest.getDistance());
ufoControl
.setPhysicsLocation(jumpGateControl2.getPhysicsLocation());
System.out.println("Warped");
} else {
// how to react when no collision occured
}
if (results2.size() > 0) {
System.out.println("Number of Collisions between"
+ ufoNode.getName() + " and " + moon.getName() + ": "
+ results2.size());
// how to react when a collision was detected
CollisionResult closest2 = results2.getClosestCollision();
System.out.println("What was hit? "
+ closest2.getGeometry().getName());
System.out.println("Where was it hit? "
+ closest2.getContactPoint());
System.out.println("Distance? " + closest2.getDistance());
}

Related

Flutter - How to use data from equal built classes?

I want to build an app for my pupil which generates tasks out of sentence blocks.
For example I created two classes, apple and pear, with nearly the same structure. They return a question built out of the sentence blocks which are defined in the classes. In both classes is a GenerateQuestion()-function for that.
Now I want to build some kind of overclass, which picks a random class of i.e. apple or pear and then returns the strings from the functions. The functions names are the same, but I can't figure out how to get data from a random choosen class. Hoping for help. Thanks in advance.
Update: Here is the code I wrote so far (I tried to translate it properly):
import 'dart:math';
int randomminmax1 = 0;
int randomminmax2 = 0;
int randomminmax3 = 0;
List classes = [apple, pear];
class overClass {
static pickClass(){
int randomClassItem = Random().nextInt(classes.length);
print(classes[randomClassItem]);
return classes[randomClassItem];
}
}
class apple {
static String giveQuestion() {
randomminmax1 = 2 + Random().nextInt(15 - 2);
randomminmax2 = randomminmax1 * (2+Random().nextInt(12 - 2));
randomminmax3 = 2 + Random().nextInt(30 - 2);
List value_1 = [" boxes", " bags", " bucket"];
List verbs = ["cost","have a price of", "are offered for"];
List value_2 = ["Euro"];
List questionWords = [""];
int randomIndexValue1 = Random().nextInt(value_1.length);
int randomIndexVerbs = Random().nextInt(verbs.length);
int randomIndexValue2 = Random().nextInt(value_2.length);
String value = randomminmax1.toString() + value_1[randomIndexValue1].toString() + " apples" + verbs[randomIndexVerbs].toString() + " " + randomminmax2.toString() + " " + value_2[randomIndexValue2].toString() + ".\n";
String question = "How much are " + randomminmax3.toString() + value_1[randomIndexValue1].toString() + "?\n";
return value + question;
}
static String giveAnswer(){
double result = (randomminmax2/randomminmax1)*randomminmax3;
return result.toStringAsFixed(2) + " Euro.";
}
}
class pear {
static String giveQuestion() {
randomminmax1 = 2 + Random().nextInt(15 - 2);
randomminmax2 = randomminmax1 * (2+Random().nextInt(12 - 2));
randomminmax3 = 2 + Random().nextInt(30 - 2);
List value_1 = [" boxes", " bags", " bucket"];
List verbs = ["cost","have a price of", "are offered for"];
List value_2 = ["Euro"];
List questionWords = [""];
int randomIndexValue1 = Random().nextInt(value_1.length);
int randomIndexVerbs = Random().nextInt(verbs.length);
int randomIndexValue2 = Random().nextInt(value_2.length);
String value = randomminmax1.toString() + value_1[randomIndexValue1].toString() + " pears" + verbs[randomIndexVerbs].toString() + " " + randomminmax2.toString() + " " + value_2[randomIndexValue2].toString() + ".\n";
String question = "How much are " + randomminmax3.toString() + value_1[randomIndexValue1].toString() + "?\n";
return value + question;
}
static String giveAnswer(){
double result = (randomminmax2/randomminmax1)*randomminmax3;
return result.toStringAsFixed(2) + " Euro.";
}
}
static String giveAnswer(){
double result = (randomminmax2/randomminmax1)*randomminmax3;
return result.toStringAsFixed(2) + " Euro.";
}
}
Can you try to create a superclass that all question classes will inherit and then get the subclasses and programmatically call functions. Try to see here
At least I managed to give my values directly from the classes into the list. But then I got problems with the int-variables, which were built wrong.
My "solution": I converted my classes into isolated flutter widgets, which works fine, except the problem that I'm not able to put the widgets into a list, from where they are picked randomly...but therefore I'll write a new post.
Thank you Moustapha for your help (the superclass idea sounds good, but way too hard to code for me) ;)!

Google Play Games leaderboard custom

I want to implement this
"my ranking : Top 13% (25034 rank)"
What I've tried↓
Social.LoadScores("CgkI1...", scores => {...})
: "scores.Length" was returned only up to 25.
ILeaderboard lb = Social.CreateLeaderboard();
lb.id = "CgkI1...";
uint max_player = lb.maxRange;
: failed..
I don't know in leaderboard player count and my rank.
please help me what can I do..
I succeeded on my own:
ILeaderboard lb = PlayGamesPlatform.Instance.CreateLeaderboard();
lb.id = "CgkI1...";
lb.userScope = UserScope.Global;
lb.range = new Range(1,10);
lb.timeScope = TimeScope.AllTime;
lb.LoadScores(scores =>
{
uint all_player = lb.maxRange;
int my_rank = lb.localUserScore.rank;
decimal percent = (decimal)my_rank / (decimal)all_player;
text.text = scores.ToString() + "\nAllPlayer: " + all_player + "\nMyRank: " + my_rank + "\nMyScore: " +lb.localUserScore.value.ToString() + "\nPercent: " + percent + "%";
});

Bukkit - Displaying null when getting a string from the config file

So I've been working on a custom feature for my minecraft server, one of the things that I need to do is get an integer from the config file that is specific to each player to display how many Packages(keys) they have (Virtual items)
The issue that I am having is that in the GUI it is displaying 'null' instead of how many they have... Could anyone help me please?
Item in the gui
Code for creating the player's instance in the config (Using a custom file class that was provided to me by a friend of mine.)
#EventHandler
public void playerJoin(PlayerJoinEvent event) {
Main main = Main.getPlugin(Main.class);
Player player = event.getPlayer();
UUID uuid = player.getUniqueId();
if (!main.getDataFolder().exists())
main.getDataFolder().mkdirs();
File file = new File(main.getDataFolder(), "players.yml");
FileConfiguration config = YamlConfiguration.loadConfiguration(file);
if (!config.contains("Users." + uuid + ".Username")) {
try {
System.out.println("Creating entry for " + player + " (" + uuid + ")");
config.set("Users." + uuid + ".Username", player);
config.set("Users." + uuid + ".Packages.Common", 0);
config.set("Users." + uuid + ".Packages.Rare", 0);
config.set("Users." + uuid + ".Packages.Epic", 0);
config.set("Users." + uuid + ".Packages.Legendary", 0);
config.set("Users." + uuid + ".Packages.Exotic", 0);
config.save(file);
System.out.println("Successfully created the entry for " + " (" + uuid + ")");
} catch (Exception e) {
}
}
}
Code for the creation of the item in the gui:
public static String inventoryname = Utils.chat("&fWhite Backpack");
public static Inventory WhiteBackpack(Player player) {
UUID uuid = player.getUniqueId();
Inventory inv = Bukkit.createInventory(null, 27, (inventoryname));
ItemStack common = new ItemStack(Material.INK_SACK);
common.setDurability((byte) 8);
ItemMeta commonMeta = common.getItemMeta();
commonMeta.setDisplayName(Utils.chat("&fCommon Packages &8» &f&l" + Main.pl.getFileControl().getConfig().getString("Users." + uuid + ".Packages.Common")));
common.setItemMeta(commonMeta);
inv.setItem(10, common);
return inv;
}
There are a couple things wrong with your code.
First, you never account for what happens if the config you are loading does not exist. When you do main.getDataFolder().mkdirs(), you account for if the folder is missing, but not the file.
Second, you are doing the following operation:
config.set("Users." + uuid + ".Username", player);
This is incorrect because the player variable is of the type Player, not of the type String. To fix this, you need to instead do the following:
config.set("Users." + uuid + ".Username", player.getName());
Third, you are attempting to write to a file that might not exist. When you initialize you file, you need to also make sure it exists, and if it does not, you need to create it. Right now you have the following:
File file = new File(main.getDataFolder(), "players.yml");
It must be changed to this block of code:
File file = new File(main.getDataFolder(), "players.yml");
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException ex) {
ex.printStackTrace();
}
}
You could just have it be created when you attempt to save the file later on, but that is not ideal since it's safer to let Bukkit write to a file that already exists.
Fourth, and I'm not necessarily sure that this is a problem per se, but you are trying to access an Integer value from the config file as if it were a String. Try to replace the following:
commonMeta.setDisplayName(Utils.chat("&fCommon Packages &8» &f&l"
+ Main.pl.getFileControl().getConfig().getString("Users." + uuid + ".Packages.Common")));
with this instead:
commonMeta.setDisplayName(Utils.chat("&fCommon Packages &8» &f&l"
+ Main.pl.getFileControl().getConfig().getInt("Users." + uuid + ".Packages.Common")));
Hope this gets you moving in the right direction!

Google maps downloadUrl does not return 200

My code is based on the example of google code:
https://developers.google.com/maps/articles/phpsqlinfo_v3
and was working fine.
I need to change a former 'gid' (Integer) field to 'id' (String) to get saved to the database and used to display a new labeled symbol on the map.
The strange thing is, that the url, that is build in the code to call the addrow.php file is OK. When I capture this string with alert(url), and I manually use this string, the new data is added to the database.
In my script, the call seems to fail (responseCode == 200 && data.length <=1), since no data is written to the database and the alert from the 'else-clause' is displayed as short pop-up.
Here's the code I use in my project (to save data from a form):
//save new marker to Postgis-database and add new markerwithlabel on the fly
function saveData(){
var gender = escape(document.getElementById("gender").value);
var hoehe = InZahl(document.getElementById("hoehe").value);
var breite = InZahl(document.getElementById("breite").value);
var id = escape(document.getElementById("id").value);
var vital = document.getElementById("vital").value;
var typ = document.getElementById("typ").value;
var ein_mehr = document.getElementById("ein_mehr").value;
var st_durchm = document.getElementById("st_durchm").value;
var frucht = document.getElementById("frucht").value;
var anmerk = document.getElementById("anmerk").value;
var latlng = marker.getPosition();
var url = "./mapdata/addrow.php?gender=" + gender +
"&hoehe=" + hoehe + "&lat=" + latlng.lat() + "&lng=" + latlng.lng() +
"&breite=" + breite + "&id=" + id + "&typ=" + typ + "&ein_mehr=" +ein_mehr + "&st_durchm=" + st_durchm +
"&frucht=" + frucht +
"&vital=" + vital + "&anmerk=" + anmerk;
downloadUrl(url, function (data, responseCode) {
if (responseCode == 200 && data.length <=1) {
infowindow.close();
marker.setDraggable(false);
marker.setIcon('./images/mm_purple.png');
marker.labelContent = id;
marker.setMap(map);
downloadUrl("./mapdata/getxml_get_last.php", function (data1) {
var xml = parseXml(data1);
var ms = xml.documentElement.getElementsByTagName("m");
var gid = ms[0].getAttribute("gid");
var html_n = "<div id='InfoWindow'><p style='font-weight:bold;'>" + id + "</p> \n\<p>Höhe:" + hoehe + " Breite: "+ breite +
"<br />\n\Typ: "+typ+" Stämme: "+ein_mehr+" St-Durchm: "+ st_durchm + "<br />\n\Vitalität: "+vital+" Fruchtbehang: "+frucht+
"<p/>\n\<p style='text-align:right;'><a href='sm_juniperus.php?operation=ssearch&ResetFilter=0&SearchField=gid&FilterType=%3D&FilterText="+ gid +
"' target='_blank'> Daten editieren </a></p></div>";
infowindow.setContent(html_n);
bindInfoWindow(marker, map, infowindow, html_n);
(function(i, marker, gid) {
var origIcon = marker.getIcon();
new LongPress(marker, 1000);
google.maps.event.addListener(marker, 'longpress', function(e) {
marker.setDraggable(true);
marker.setIcon(mmcross);
});
google.maps.event.addListener(marker, 'dragend', function(){
updatePosition(marker, gid);
marker.setIcon(origIcon);
});
})(i,marker,gid);
//add new marker to markerCluster-Array and to markerArray
markerCluster.addMarker(marker,false);
markerArray.push(marker);
i++;
}); // End add new marker
}
else {
alert("Your data couldn't be saved!");
}
}); // End downloadUrl
}; // END saveData()
As I said, my code worked fine, but after 3 evenings passed to solve this, I thought it would be time to ask for help.
If anybody has an idea, where the mistake lies, I would apreciate any hint.
Just to confirm, you're aware that you by doing
if (responseCode == 200 && data.length <=1) {
you are saying 'if the request is successful and the data it returns is only one character or below in length'? I am unsure if this is intended or not, because this way the code inside the if statement is only ran if the response is successful but contains only 1 or 0 characters.

Mongo dbref additional fields are invisible in mongoshell. How to display them?

Background: This problem came up with Doctrine ODM, that uses a _doctrine_class_name field in DBRefs that is invisible in the Mongo shell (2.2.2) and caused quite a culprit, when we had to update a record manually.
Example:
mongoshell> use testdb; // for safety
mongoshell> a = DBRef("layout_block", ObjectId("510a71fde1dc610965000005")); // create a dbref
mongoshell> a.hiddenfield = "whatever" // add a field that's normally not there like Doctrine does
mongoshell> a // view it's contents, you won't see hiddenfield
mongoshell> for (k in a) { var val = a[k]; print( k + "(" + typeof(val) + "): " + val ); } // you can see that there's more if you iterate through it
mongoshell> db.testcoll.save({ref: [ a ]}) // you can have it in a collection
mongoshell> db.testcoll.findOne(); // and normally you won't see it
Without an iteration like the third command from below (or MongoVue), you won't ever know there's more in a DBRef if you simply use find(). I have not found any usable modifier for find()(tried: toArray, tojson, printjson, toString, hex, base64, pretty, chatty, verbose, ...).
Has anybody got a method to display DBRef contents verbosely in mongo shell?
The Mongo shell is an extension of Mozilla SpiderMonkey (1.7?) and has pretty bare bones functionality.
The suggestion from a MongoDB blog post on the shell is to define the following inspect function in .mongorc.js in your home directory
function inspect(o, i) {
if (typeof i == "undefined") {
i = "";
}
if (i.length > 50) {
return "[MAX ITERATIONS]";
}
var r = [];
for (var p in o) {
var t = typeof o[p];
r.push(i + "\"" + p + "\" (" + t + ") => " +
(t == "object" ? "object:" + inspect(o[p], i + " ") : o[p] + ""));
}
return r.join(i + "\n");
}
Additionally you can redefine the DBRef.toString function as something like:
DBRef.prototype.toString = function () {
var r = ['"$ref": ' + tojson(this.$ref), '"$id": ' + tojson(this.$id)];
var o = this;
for (var p in o) {
if (p !== '$ref' && p !== '$id') {
var t = typeof o[p];
r.push('"' + p + '" (' + t + ') : ' +
(t == 'object' ? 'object: {...}' : o[p] + ''));
}
}
return 'DBRef(' + r.join(', ') + ')';
};