Im making a jumper game. The objetive is stay alive jumping platforms.
I start the game with my character and 3 platforms. The next platforms I generate randomly with a timerhandler.
Its almost ready but Im facing some problems with a timerhandler.
Im using it to spawn platforms (static bodys) once every second.
private void addPlat(int x, int y)
{
platform = new Platform(x, y, vbom, physicsWorld);
attachChild(platform);
}
private void createPlatSpawn()
{
float mEffectSpawnDelay = 1f;
platSpawnTimerHandler = new TimerHandler(mEffectSpawnDelay, true, new ITimerCallback()
{
#Override
public void onTimePassed(TimerHandler pTimerHandler) {
platformList.add(platform);
if (platformList.getLast().getY() >= 240 && platformList.getLast().getY() < 400)
{
yCoord = (int) (platform.getY() - addNumber.nextInt(160));
}
else if (platformList.getLast().getY() < 240 && platformList.getLast().getY() >= 50)
{
yCoord = (int) (platform.getY() + addNumber.nextInt(160));
}
xCoord = (int) (platform.getX() + 200);
addPlat(xCoord, yCoord);
}
});
resourcesManager.engine.registerUpdateHandler(platSpawnTimerHandler);
}
To jump I use a variable footContacts, when its positive it can jump, otherwise it cant
Here the contact listener
private ContactListener contactListener()
{
ContactListener contactListener = new ContactListener()
{
public void beginContact(Contact contact)
{
final Fixture x1 = contact.getFixtureA();
final Fixture x2 = contact.getFixtureB();
if (x1.getBody().getUserData() != null && x2.getBody().getUserData() != null)
{
if (x2.getBody().getUserData().equals("player"))
{
player.increaseFootContacts();
}
}
}
public void endContact(Contact contact)
{
final Fixture x1 = contact.getFixtureA();
final Fixture x2 = contact.getFixtureB();
if (x1.getBody().getUserData() != null && x2.getBody().getUserData() != null)
{
if (x2.getBody().getUserData().equals("player"))
{
player.decreaseFootContacts();
}
}
}
public void preSolve(Contact contact, Manifold oldManifold)
{
}
public void postSolve(Contact contact, ContactImpulse impulse)
{
}
};
return contactListener;
}
Here is the method inside the class Player, to make him jump
public void jump()
{
if (footContacts < 1)
{
return;
}
body.setLinearVelocity(new Vector2(body.getLinearVelocity().x, 15));
}
The first 3 platforms the jump action works perfectly but when he interact with the platforms created by the timerhandler, it doesnt work. Anyone can help me?
Adding the method to create the first 3 platforms:
private void createFirstPlat()
{
addPlat(200, 200);
addPlat(400, 300);
addPlat(600, 150);
}
Class Platform
public class Platform extends Sprite{
private Body body;
public Platform(float pX, float pY, VertexBufferObjectManager vbo, PhysicsWorld physicsWorld)
{
super(pX, pY, ResourcesManager.getInstance().platform_region, vbo);
createPhysics(physicsWorld);
// TODO Auto-generated constructor stub
}
private void createPhysics (PhysicsWorld physicsWorld)
{
body = PhysicsFactory.createBoxBody(physicsWorld, this, BodyType.StaticBody, PhysicsFactory.createFixtureDef(0, 0, 0.5f));
body.setUserData("platform");
physicsWorld.registerPhysicsConnector(new PhysicsConnector(this, body, true, false)
{
#Override
public void onUpdate(float pSecondsElapsed)
{
super.onUpdate(pSecondsElapsed);
}
});
}
}
You should have post more code where you manually crate those 3 working platforms. It's possible that the problem is in .setUserData which I can't see because you haven't posted your Platform class as well.
Another possible problem is that you don't attach it to right entity or there is a problem with physiscsConnector which you maybe don't initialize. Try to create
public Entity foregroundLayer = new Entity();
and attach it to the scene. Then in addPlat use
foregroundLayer.attachChild(platform)
If that won't help please paste your Platform class and how you create them for first three times.
PS By the way, it's great solution when you want to control layers. For example you want some sprites to be on top and some sprites to be on background while overlapping. The important thing is attaching order so you first attach backgroundLayer and then foregroundLayer. Finally you can attach other entites for those two layers at any time and it will be shown as you expect.
Related
im trying to create an android plugin and import it in unity but i always get 0 as return value from the plugin method and i cant fix this issue.
Here is what i did:
AndroidStudio:
-Created a new project
-Created a library module (package: com.e.timerlibrary)
-Created Public Class "MyPlugin"
-Build -> "Make Module 'timerlibrary'"
-copied "classes.jar" file into "Assets/Plugins/Android" in Unity
MyPlugin only has one method:
public int testmethode(){
return 100;
}
Unity:
AndroidJavaObject JavaTimerClass = new AndroidJavaObject("com.e.timerlibrary.MyPlugin");
TextPlugin.text = JavaTimerClass.Call<int>("testmethode").ToString();
TextPlugin.text should display "100" but its always 0.
It seems like the name of the package cant be found
Hopefully someone can help me. Im new to unity&Androidstudio and followed many tutorials on youtube but i cant fix this issue.
Here is my full c# code. it's basically a timer.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class CountDownTimer : MonoBehaviour
{
public float timeValue = 0;
public float timeValuePause = 0;
public float sliderValue;
public Slider slider;
public Text textTimer;
public Text textTimerBtn;
public Text TextPlugin;
bool timerActive = false;
bool backTimerActive = false;
AndroidJavaObject JavaTimerClass = new AndroidJavaObject("com.e.timerlibrary.MyPlugin");
int testvar1;
// Start is called before the first frame update
void Start()
{
textTimer.text = timeValue.ToString();
//startService();
}
// Update is called once per frame
void Update()
{
if (timerActive)
{
timeValue -= Time.deltaTime;
textTimer.text = timeValue.ToString("f0");
slider.value = timeValue;
if (timeValue <= 0)
{
timerActive = false;
textTimerBtn.text = "Start";
timeValue = 0;
slider.interactable = true;
}
}
}
public void OnTimerBtnClick()
{
textTimerBtn.text = timerActive ? "Start" : "Stop";
timerActive = !timerActive;
slider.interactable = false;
if (timerActive==false)
{
timeValue = 0;
textTimer.text = timeValue.ToString("f0");
slider.interactable = true;
slider.value = 0;
}
}
public void GetValueOfSlider(float value)
{
if (timerActive == false)
{
textTimer.text = value.ToString("f0");
timeValue = value;
}
}
void OnApplicationPause(bool pause) //Wird nur jeweils 1 mal ausgeführt!!
{
if (pause)
{
//startService1();
//TextPlugin.text = "pause";
TextPlugin.text = JavaTimerClass.Call<int>("testmethode").ToString();
}
else
{
//TextPlugin.text = "unpause";
stopService1();
}
}
void startService1()
{
/* if (!backTimerActive)
{
JavaTimerClass.Call("StartTimerService");
backTimerActive = true;
} */
TextPlugin.text = JavaTimerClass.Call<int>("testmethode").ToString();
//TextPlugin.text = JavaTimerClass.Call<int>("GetTime").ToString();
}
void stopService1()
{
//TextPlugin.text = JavaTimerClass.Call<int>("StopTimerService").ToString();
backTimerActive = false;
}
}
here is java code:
package com.e.timerlibrary;
public class MyPlugin {
public int testmethode(){
return 100;
}
}
i know it looks pretty bad but im only trying to get the plugin to work
I am trying to generate a depth map from the point cloud. I know that I can project the point cloud to the image plane, however there is already a function (ScreenCoordinateToWorldNearestNeighbor) in the TangoSupport script that finds the XYZ point given a screen coordinate.
I am unable to get this support function to work, and it seems that one or more of my inputs are invalid. I am updating my depthmap texture in the OnTangoDepthAvailable event.
public void OnTangoDepthAvailable(TangoUnityDepth tangoDepth)
{
_depthAvailable = true;
Matrix4x4 ccWorld = _Camera.transform.localToWorldMatrix;
bool isValid = false;
Vector3 colorCameraPoint = new Vector3();
for (int i = 0; i < _depthMapSize; i++)
{
for (int j = 0; j < _depthMapSize; j++)
{
if (TangoSupport.ScreenCoordinateToWorldNearestNeighbor(
_PointCloud.m_points, _PointCloud.m_pointsCount,
tangoDepth.m_timestamp,
_ccIntrinsics,
ref ccWorld,
new Vector2(i / (float)_depthMapSize, j / (float)_depthMapSize),
out colorCameraPoint, out isValid) == Common.ErrorType.TANGO_INVALID)
{
_depthTexture.SetPixel(i, j, Color.red);
continue;
}
if (isValid)
{
//_depthTexture.SetPixel(i, j, new Color(colorCameraPoint.z, colorCameraPoint.z, colorCameraPoint.z));
_depthTexture.SetPixel(i, j,
new Color(0,UnityEngine.Random.value,0));
}
else
{
_depthTexture.SetPixel(i, j, Color.white);
}
}
}
_depthTexture.Apply();
_DepthMapQuad.material.mainTexture = _depthTexture;
}
If I had to guess, I would say that I am passing in the wrong matrix (ccWorld). Here is what it says in the documents for the matrix param:
Transformation matrix of the color camera with respect to the Unity
world frame.
The result is a white depth map, which means that the function is returning successfully, however the isValid is false meaning that it couldn't find any nearby point cloud point after projection.
Any ideas? Also I noticed that the performance is pretty bad, even when my depth map is 8x8. Should I not be updating the depthmap when ever new depth data is available (inside OnTangoDepthAvailable)?
Edit:
I was able to make the function return successfully, however now it doesn't find a point cloud point nearby after projection. The resulting depth map is always white. I am printing out all the arguments, and it all looks correct, so I think I am passing in the wrong matrix.
You should update your SDK and Project Tango Dev Kit. Here is an example of getting depth map on Android, perhaps you get a hint for unity:
public class MainActivity extends AppCompatActivity {
private Tango mTango;
private TangoConfig mTangoConfig;
private TangoPointCloudManager mPointCloudManager;
private AtomicBoolean tConnected = new AtomicBoolean(false);
Random rand = new Random();
private ImageView imageDepthMap;
private static final ArrayList<TangoCoordinateFramePair> framePairs = new ArrayList<TangoCoordinateFramePair>();
{
framePairs.add(new TangoCoordinateFramePair(
TangoPoseData.COORDINATE_FRAME_CAMERA_DEPTH,
TangoPoseData.COORDINATE_FRAME_DEVICE));
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//initialize the imageView
imageDepthMap = (ImageView)findViewById(R.id.imageView);
//initialize pointCloudManager
mPointCloudManager = new TangoPointCloudManager();
}
#Override
protected void onResume(){
super.onResume();
//obtain the tango configuration
if(tConnected.compareAndSet(false, true)) {
try {
setTango();
} catch (TangoOutOfDateException tE) {
tE.printStackTrace();
}
}
}
#Override
protected void onPause(){
super.onPause();
if(tConnected.compareAndSet(true, false)) {
try {
//disconnect Tango service so other applications can use it
mTango.disconnect();
} catch (TangoException e) {
e.printStackTrace();
}
}
}
private void setTango(){
mTango = new Tango(MainActivity.this, new Runnable() {
#Override
public void run() {
TangoSupport.initialize();
mTangoConfig = new TangoConfig();
mTangoConfig = mTango.getConfig(TangoConfig.CONFIG_TYPE_CURRENT);
mTangoConfig.putBoolean(TangoConfig.KEY_BOOLEAN_DEPTH, true); //activate depth sensing
mTango.connect(mTangoConfig);
mTango.connectListener(framePairs, new Tango.OnTangoUpdateListener() {
#Override
public void onPoseAvailable(TangoPoseData tangoPoseData) {
}
#Override
public void onXyzIjAvailable(TangoXyzIjData pointCloud) {
// Log.d("gDebug", "xyZAvailable");
//TangoXyzIjData pointCloud = mPointCloudManager.getLatestXyzIj();
// Update current camera pose
if (pointCloud.ijRows * pointCloud.ijCols > 0){
try {
// Calculate the last camera color pose.
TangoPoseData lastFramePose = TangoSupport.getPoseAtTime(0,
TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE,
TangoPoseData.COORDINATE_FRAME_CAMERA_COLOR,
TangoSupport.TANGO_SUPPORT_ENGINE_OPENGL, 0);
if (pointCloud != null) {
//obtain depth info per pixel
TangoSupport.DepthBuffer depthBuf = TangoSupport.upsampleImageNearestNeighbor(pointCloud, mTango.getCameraIntrinsics(TangoCameraIntrinsics.TANGO_CAMERA_COLOR), lastFramePose);
//create Depth map
int[] intBuff = convertToInt(depthBuf.depths, depthBuf.width, depthBuf.height);
final Bitmap Image = Bitmap.createBitmap(intBuff, depthBuf.width, depthBuf.height, Bitmap.Config.ARGB_8888);
runOnUiThread(new Runnable() {
#Override
public void run() {
imageDepthMap.setImageBitmap(Image);
}
});
}
} catch (TangoErrorException e) {
Log.e("gDebug", "Could not get valid transform");
}
}
}
#Override
public void onFrameAvailable(int i) {
//Log.d("gDebug", "Frame Available from " + i);
}
#Override
public void onTangoEvent(TangoEvent tangoEvent) {
}
});
}
});
}
private int[] convertToInt(FloatBuffer pointCloudData, int width, int height){
double mulFact = 255.0/5.0;
int byteArrayCapacity = width * height;
int[] depthMap = new int[byteArrayCapacity];
int grayPixVal = 0;
pointCloudData.rewind();
for(int i =0; i < byteArrayCapacity; i++){
//obtain grayscale representation
grayPixVal = (int)(mulFact * (5.0- pointCloudData.get(i)));
depthMap[i] = Color.rgb(grayPixVal, grayPixVal, grayPixVal);
}
return depthMap;
}
}
I extracted this code from my already working version. Try to fix any config related errors. The code assumes depth sensing range of 0.4m - 5m in depth estimation. Mapping zero to 255 allows regions which were not estimated (value of zero) to be white.
When I look(focusing gazepointer over cube) on the cube teleport (vanishes and then come to new place), I want to add some time delay between its teleport activity.
1.)Teleport.cs
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(Collider))]
public class Teleport : MonoBehaviour {
private Vector3 startingPosition;
void Start() {
startingPosition = transform.localPosition;
SetGazedAt(false);
}
public void SetGazedAt(bool gazedAt) {
GetComponent<Renderer>().material.color = gazedAt ? Color.green : Color.red;
}
public void Reset() {
transform.localPosition = startingPosition;
}
public void ToggleVRMode() {
Cardboard.SDK.VRModeEnabled = !Cardboard.SDK.VRModeEnabled;
}
public void TeleportRandomly() {
Vector3 direction = Random.onUnitSphere;
direction.y = Mathf.Clamp(direction.y, 0.5f, 1f);
float distance = 2 * Random.value + 1.5f;
transform.localPosition = direction * distance;
}
}
2.)Teleportlegacy.cs
using UnityEngine;
using System.Collections;
public class TeleportLegacyUI : Teleport {
private CardboardHead head;
void Awake() {
head = Camera.main.GetComponent<StereoController>().Head;
CardboardOnGUI.IsGUIVisible = true;
CardboardOnGUI.onGUICallback += this.OnGUI;
}
void Update() {
RaycastHit hit;
bool isLookedAt = GetComponent<Collider>().Raycast(head.Gaze, out hit, Mathf.Infinity);
SetGazedAt(isLookedAt);
if (Cardboard.SDK.Triggered && isLookedAt) {
print("gazed");
///maaaaibbbbbbbnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
TeleportRandomly();
//Update2();
}
}
void OnGUI() {
if (!CardboardOnGUI.OKToDraw(this)) {
return;
}
if (GUI.Button(new Rect(50, 50, 200, 50), "Reset")) {
Reset();
}
if (GUI.Button(new Rect(50, 110, 200, 50), "Recenter")) {
Cardboard.SDK.Recenter();
}
if (GUI.Button(new Rect(50, 170, 200, 50), "VR Mode")) {
ToggleVRMode();
}
}
void OnDestroy() {
CardboardOnGUI.onGUICallback -= this.OnGUI;
}
}
How should I make the time delay between the teleport activity of cube?
I'd suggest a coroutine, you might need to add a flag or something to avoid it getting double triggered (you could reset it at the end of the coroutine)
public IEnumerator TeleportCoroutine()
{
yield return new WaitForSeconds(3.5f);
Vector3 direction = Random.onUnitSphere;
direction.y = Mathf.Clamp(direction.y, 0.5f, 1f);
float distance = 2 * Random.value + 1.5f;
transform.localPosition = direction * distance;
}
public void TeleportRandomly() {
StartCoroutine(TeleportCoroutine());
}
Edit: If you'd like the object to warp after being gazed at for a certain amount of time, try:
using UnityEngine;
using System.Collections;
public class TeleportLegacyUI : Teleport {
private CardboardHead head;
private float gazeTotalTime = 0;
void Awake()
{
head = Camera.main.GetComponent<StereoController>().Head;
CardboardOnGUI.IsGUIVisible = true;
CardboardOnGUI.onGUICallback += this.OnGUI;
}
void Update() {
RaycastHit hit;
bool isLookedAt = GetComponent<Collider>().Raycast(head.Gaze, out hit, Mathf.Infinity);
SetGazedAt(isLookedAt);
if(isLookedAt)
gazeTotalTime += Time.deltaTime;
else
gazeTotalTime = 0;
if(gazeTotalTime > 1.0f)
TeleportRandomly();
}
void OnGUI() {
if (!CardboardOnGUI.OKToDraw(this)) {
return;
}
if (GUI.Button(new Rect(50, 50, 200, 50), "Reset")) {
Reset();
}
if (GUI.Button(new Rect(50, 110, 200, 50), "Recenter")) {
Cardboard.SDK.Recenter();
}
if (GUI.Button(new Rect(50, 170, 200, 50), "VR Mode")) {
ToggleVRMode();
}
}
void OnDestroy() {
CardboardOnGUI.onGUICallback -= this.OnGUI;
}
}
I am using metaio sdk 6.0.2. i am working on metaio INSTANT_2D_GRAVITY tracking and was able to display 3d model. I want to display same 3d model when tracking is lost.but I am failing to do so. I tried by adding trackingValuesVector in onTrackingEvent of MetaioSDKCallbackHandler with no success. can anyone tell me where am I going wrong?
private TrackingValues mTrackingValues;// declared globally
private IGeometry mModel; // declared globally
private boolean mPreview=true;// declared globally
// start INSTANT_2D_GRAVITY tracking
public void onTakePicture(View v)
{
captureTrackingValues = true;
metaioSDK.startInstantTracking("INSTANT_2D_GRAVITY", new File(""), mPreview);
mPreview = !mPreview;
}
final class MetaioSDKCallbackHandler extends IMetaioSDKCallback
{
#Override
public void onInstantTrackingEvent(final boolean success,final File filePath) {
super.onInstantTrackingEvent(success, filePath);
if(mSurfaceView != null)
{
mSurfaceView.queueEvent(new Runnable() {
#Override
public void run() {
if(success)
{
if(captureTrackingValues == true)
{
metaioSDK.setTrackingConfiguration(filePath);
Log.i("Tracking value success","good");
}
}
else
{
Log.i("Tracking value failure","bad");
}
}
});
}
}
#Override
public void onTrackingEvent(TrackingValuesVector trackingValuesVector) {
super.onTrackingEvent(trackingValuesVector);
if (!trackingValuesVector.isEmpty())
{
for(int i =0;i< trackingValuesVector.size();i++)
{
if(trackingValuesVector.get(i).isTrackingState() && mModel!=null)
{
mTrackingValues = metaioSDK.getTrackingValues(i);
mModel.setCoordinateSystemID(trackingValuesVector.get(i).getCoordinateSystemID());
}
else {
if(mModel!= null && mTrackingValues != null) {
metaioSDK.setCosOffset(1, mTrackingValues);
//mChairModel.setCoordinateSystemID(0);
Log.e("TestAR","isTrackingState is null");
}
}
}
}
else{
if(mModel!= null && mTrackingValues != null) {
metaioSDK.setCosOffset(1, mTrackingValues);
//mModel.setCoordinateSystemID(0);
Log.e("TestAR","trackingValuesVector is null");
}
}
}
}
loading 3d model:
private void loadModel()
{
if (mSurfaceView != null) {
mSurfaceView.queueEvent(new Runnable() {
#Override
public void run() {
File chairModel = AssetsManager.getAssetPathAsFile(getApplicationContext(),"chair.obj");
if (chairModel != null) {
mModel = metaioSDK.createGeometry(chairModel);
mModel.setScale(3f);
mModel.setTranslation(new Vector3d(0f,0f,-60f));
mGestureHandler.addObject(mModel, 1);
mModel.setRotation(new Rotation(0f, 0.5f, 0f));
mModel.setCoordinateSystemID(1);
}
}
});
}
else
{
Log.e("exception", "msurfaceview is null");
}
}
I see that you also tried setting the model to COS 0. This should actually work, if the tracking is lost.
If you do not see the model, you would have to play around with the scale value (i.e. set a low value like 0.01) and with the Z translation value. Set a negative Z value in order to move the model away from the camera clipping plane.
I am creating an andengine game (with reference to this tutorial http://www.matim-dev.com/full-game-tutorial---part-1.html), where my main charachter walks and gets hit by the falling bricks from the top. He dies if he is hit by a falling brick. But once the brick is on the ground, the main charachter can touch it and jump on it. Now I know how to find if two bodies contact with each other. But how to find if the contact is on the upper side of the charachter or the left or right side of the body.
My code used for contact is as follows
private ContactListener contactListener()
{
ContactListener contactListener = new ContactListener()
{
public void beginContact(Contact contact)
{
final Fixture x1 = contact.getFixtureA();
final Fixture x2 = contact.getFixtureB();
Vector2[] contactPoints = contact.getWorldManifold().getPoints();
System.out.println("the points are as ::"+contactPoints);
if (x1.getBody().getUserData() != null && x2.getBody().getUserData() != null)
{
if (x2.getBody().getUserData().equals("player"))
{
player.increaseFootContacts();
}
if (x1.getBody().getUserData().equals("platform2") && x2.getBody().getUserData().equals("player"))
{
engine.registerUpdateHandler(new TimerHandler(0.2f, new ITimerCallback()
{
public void onTimePassed(final TimerHandler pTimerHandler)
{
pTimerHandler.reset();
engine.unregisterUpdateHandler(pTimerHandler);
x1.getBody().setType(BodyType.DynamicBody);
}
}));
}
if (x1.getBody().getUserData().equals("platform3") && x2.getBody().getUserData().equals("player"))
{
x1.getBody().setType(BodyType.DynamicBody);
}
}
}
public void endContact(Contact contact)
{
final Fixture x1 = contact.getFixtureA();
final Fixture x2 = contact.getFixtureB();
if (x1.getBody().getUserData() != null && x2.getBody().getUserData() != null)
{
if (x2.getBody().getUserData().equals("player"))
{
player.decreaseFootContacts();
}
}
}
public void preSolve(Contact contact, Manifold oldManifold)
{
}
public void postSolve(Contact contact, ContactImpulse impulse)
{
}
};
return contactListener;
}
Please suggest me some ideas.
does this help you enough or you need more information about body contact methods?
public boolean areBodiesContacted(Body pBody1, Body pBody2,
Contact pContact)
{
if(pContact.getFixtureA().getBody().equals(pBody1) ||
pContact.getFixtureB().getBody().equals(pBody1))
if(pContact.getFixtureA().getBody().equals(pBody2) ||
pContact.getFixtureB().getBody().equals(pBody2))
return true;
return false;
}