I have been working on this gimbal code for a while now trying to get my camera gimbal on my DJI Matrice 100 drone to slightly move every time you press the button direction. I tried using a for and while loop to increment the angle values but it seems to only read the angle inside the loop and not the loop itself. Does anyone have any suggestions for how to get the gimbal to increment angles onClick?
This is the code for the gimbal rotation. (Note:The for loop line I was testing is commented out. Last tested the while loop.):
private void rotateGimbalToMin (Button button) {
DJIGimbal gimbal = getGimbalInstance();
if (gimbal == null){
return;
}
Object key = getCorrespondingKeyWithButton(button);
Number minValue = ((DJIParamMinMaxCapability)(gimbal.gimbalCapability().get(key))).getMin();
if (key == DJIGimbalCapabilityKey.AdjustPitch){ //down
//for(double anglex = 0; anglex >= -180;anglex+= -20) {
while(anglex != -180){
mPitchRotation.direction = DJIGimbalRotateDirection.Clockwise;
mPitchRotation.angle = -20; //TODO minValue.floatValue()
anglex+= -20;
}
}
if(key == DJIGimbalCapabilityKey.AdjustYaw){ //left
//for(double anglex = 0; anglex <= 180; anglex+=20) {//test for loop
while(anglex != 180){
mYawRotation.direction = DJIGimbalRotateDirection.Clockwise;
mYawRotation.angle = 20; //TODO minValue.floatValue()
anglex+=20;
}
}
sendRotateGimbalCommand();
}
private void rotateGimbalToMax(Button button) {
DJIGimbal gimbal = getGimbalInstance();
if (gimbal == null){
return;
}
Object key = getCorrespondingKeyWithButton(button);
Number maxValue = ((DJIParamMinMaxCapability)(gimbal.gimbalCapability().get(key))).getMax();
if (key == DJIGimbalCapabilityKey.AdjustPitch){ //up
//for(double anglex = 0; anglex <= 40; anglex+=20) {//test for loop
while(anglex != 40){
mPitchRotation.direction = DJIGimbalRotateDirection.Clockwise;
mPitchRotation.angle = 10; //TODO maxValue.floatValue()
this.anglex+=10;
}
}
if(key == DJIGimbalCapabilityKey.AdjustYaw){ //right
//for(double anglex = 0; anglex >= -180; anglex+=-20) {
while(anglex != -180){
mYawRotation.direction = DJIGimbalRotateDirection.Clockwise;
mYawRotation.angle = -20; //TODO maxValue.floatValue()
anglex+= -20;
}
}
// if(key == DJIGimbalCapabilityKey.AdjustRoll){
// mRollRotation.direction = DJIGimbalRotateDirection.Clockwise;
// mRollRotation.angle = maxValue.floatValue();
// }
sendRotateGimbalCommand();
}
Below is the OnClick code:
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_capture:{
captureAction();
break;
}
case R.id.btn_shoot_photo_mode:{
switchCameraMode(DJICameraSettingsDef.CameraMode.ShootPhoto);
break;
}
case R.id.btn_record_video_mode:{
switchCameraMode(DJICameraSettingsDef.CameraMode.RecordVideo);
break;
}
case R.id.btn_goLeft:{
rotateGimbalToMax((Button)v);
break;
}
case R.id.btn_goRight:{
rotateGimbalToMin((Button) v);
break;
}
case R.id.btn_goDown:{
rotateGimbalToMin((Button) v);
break;
}
case R.id.btn_goUp:{
rotateGimbalToMax((Button) v);
break;
}
case R.id.btn_reset:{
mPitchRotation.angle = 0;
mYawRotation.angle = 0;
default:
break;
}
}
Related
I am currently developing an android game using LibGdx. I am trying to get the multi touch functionality working as the game requires the player to have one thumb to control the character and the other to click buttons.
Code:
for (int i = 0; i < 2; i++) {
if (Gdx.input.isTouched(i)) {
final int iX = Gdx.input.getX(i);
if (iX > screenwidth - screenwidth / 14) {
buttontouch = true;
} else {
buttontouch = false;
}
if (iX <= screenwidth - screenwidth / 14) {
playertouch = true;
}else{
playertouch = false;
}
}
}
if (playertouch){
etc...
}
if(buttontouch){
etc...
}
The player can be moved and the buttons pressed, but not at the same time :( ... which is what i need.
Any help would be greatly appreciated! Thanks in advance.
Logic which moves your character should be called inside for circle. You should move your character every circle iteration (if button was clicked) Like this:
for (int i = 0; i < 2; i++) {
if (Gdx.input.isTouched(i)) {
final int iX = Gdx.input.getX(i);
if (iX > screenwidth - screenwidth / 14) {
buttontouch = true;
} else {
buttontouch = false;
}
if (iX <= screenwidth - screenwidth / 14) {
playertouch = true;
}else{
playertouch = false;
}
}
//Logic here!
if (playertouch){
etc...
}
if(buttontouch){
etc...
}
}
Ok I seemed to have worked out an answer.
added
if (Gdx.input.isTouched(i)) {
below in each boolean if
for (int i = 0; i < 2; i++) {
if (Gdx.input.isTouched(i)){
final int iX = Gdx.input.getX(i);
if (iX > screenwidth - screenwidth / 14) {
buttontouch = true;
} else {
buttontouch = false;
}
if (iX <= screenwidth - screenwidth / 14) {
playertouch = true;
}else{
playertouch = false;
}
}
}
//Logic here!
if (playertouch){
if (Gdx.input.isTouched(i)) {
etc...
}
}
if(buttontouch){
if (Gdx.input.isTouched(i)) {
etc...
}
}
}
I am writing an Android game right now and I would need some help in the collision of the wall on screen. When I drag the ball in the top and right it able to collide in wall but when I drag it faster it was able to overlap in the wall
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
// if the player moves
case MotionEvent.ACTION_MOVE: {
if (playerTouchRect.contains(x, y)) {
boolean left = false;
boolean right = false;
boolean up = false;
boolean down = false;
boolean canMove = false;
boolean foundFinish = false;
if (x != pLastXPos) {
if (x < pLastXPos) {
left = true;
} else {
right = true;
}
pLastXPos = x;
}
if (y != pLastYPos) {
if (y < pLastYPos) {
up = true;
} else {
down = true;
}
pLastYPos = y;
}
plCellRect = getRectFromPos(x, y);
newplRect.set(playerRect);
newplRect.left = x - (int) (playerRect.width() / 2);
newplRect.right = x + (int) (playerRect.width() / 2);
newplRect.top = y - (int) (playerRect.height() / 2);
newplRect.bottom = y + (int) (playerRect.height() / 2);
int currentRow = 0;
int currentCol = 0;
currentRow = getRowFromYPos(newplRect.top);
currentCol = getColFromXPos(newplRect.right);
if(!canMove){
canMove = mapManager.getCurrentTile().pMaze[currentRow][currentCol] == Cell.wall;
canMove =true;
}
finishTest = mapManager.getCurrentTile().pMaze[currentRow][currentCol];
foundA = finishTest == Cell.valueOf(letterNotGet + "");
canMove = mapManager.getCurrentTile().pMaze[currentRow][currentCol] != Cell.wall;
canMove = (finishTest == Cell.floor || finishTest == Cell.pl) && canMove;
if (canMove) {
invalidate();
setTitle();
}
if (foundA) {
mapManager.getCurrentTile().pMaze[currentRow][currentCol] = Cell.floor;
// finishTest
letterGotten.add(letterNotGet);
playCurrentLetter();
/*sounds.play(sExplosion, 1.0f, 1.0f, 0, 0, 1.5f);*/
foundS = letterNotGet == 's';
letterNotGet++;
}if(foundS){
AlertDialog.Builder builder = new AlertDialog.Builder(mainActivity);
builder.setTitle(mainActivity.getText(R.string.finished_title));
LayoutInflater inflater = mainActivity.getLayoutInflater();
View view = inflater.inflate(R.layout.finish, null);
builder.setView(view);
View closeButton =view.findViewById(R.id.closeGame);
closeButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View clicked) {
if(clicked.getId() == R.id.closeGame) {
mainActivity.finish();
}
}
});
AlertDialog finishDialog = builder.create();
finishDialog.show();
}
else {
Log.d(TAG, "INFO: updated player position");
playerRect.set(newplRect);
setTouchZone();
updatePlayerCell();
}
} // end of (CASE) if playerTouch
break;
} // end of (SWITCH) Case motion
}//end of Switch
return true;
}//end of TouchEvent
private void finish() {
// TODO Auto-generated method stub
}
public int getColFromXPos(int xPos) {
val = xPos / (pvWidth / mapManager.getCurrentTile().pCols);
if (val == mapManager.getCurrentTile().pCols) {
val = mapManager.getCurrentTile().pCols - 1;
}
return val;
}
/**
* Given a y pixel position, return the row of the cell it is in This is
* used when determining the type of adjacent Cells.
*
* #param yPos
* y position in pixels
* #return The cell this position is in
*/
public int getRowFromYPos(int yPos) {
val = yPos / (pvHeight / mapManager.getCurrentTile().pRows);
if (val == mapManager.getCurrentTile().pRows) {
val = mapManager.getCurrentTile().pRows - 1;
}
return val;
}
/**
* When preserving the position we need to know which cell the player is in,
* so calculate it from the centre on its Rect
*/
public void updatePlayerCell() {
plCell.x = (playerRect.left + (playerRect.width() / 2))
/ (pvWidth / mapManager.getCurrentTile().pCols);
plCell.y = (playerRect.top + (playerRect.height() / 2))
/ (pvHeight / mapManager.getCurrentTile().pRows);
if (mapManager.getCurrentTile().pMaze[plCell.y][plCell.x] == Cell.floor) {
for (int row = 0; row < mapManager.getCurrentTile().pRows; row++) {
for (int col = 0; col < mapManager.getCurrentTile().pCols; col++) {
if (mapManager.getCurrentTile().pMaze[row][col] == Cell.pl) {
mapManager.getCurrentTile().pMaze[row][col] = Cell.floor;
break;
}
}
}
mapManager.getCurrentTile().pMaze[plCell.y][plCell.x] = Cell.pl;
}
}
public Rect getRectFromPos(int x, int y) {
calcCell.left = ((x / cellWidth) + 0) * cellWidth;
calcCell.right = calcCell.left + cellWidth;
calcCell.top = ((y / cellHeight) + 0) * cellHeight;
calcCell.bottom = calcCell.top + cellHeight;
Log.d(TAG, "Rect: " + calcCell + " Player: " + playerRect);
return calcCell;
}
public void setPlayerRect(Rect newplRect) {
playerRect.set(newplRect);
}
private void setTouchZone() {
playerTouchRect.set(
playerRect.left - playerRect.width() / TOUCH_ZONE,
playerRect.top - playerRect.height() / TOUCH_ZONE,
playerRect.right + playerRect.width() / TOUCH_ZONE,
playerRect.bottom + playerRect.height() / TOUCH_ZONE);
}
public Rect getPlayerRect() {
return playerRect;
}
public Point getPlayerCell() {
return plCell;
}
public void setPlayerCell(Point cell) {
plCell = cell;
}
}*
This is an architectural problem. You can read more about it here.
In essence, your physics simulation (as simple as might be) is coupled to your framerate (which is capped at 60fps). Any events occurring faster than 60Hz cannot be processed accurately hence your bug.
The solution is to run the collision detection on an independent thread and draw the state it calculates at 60fps.
Also, take a look at these gamedev questions that refer to the same article.
I got a (to me, at least) very strange situation.
I am trying to rewrite snake, and moving is going very well, only the snake is eating itself, although I am removing 1 segment, and adding 1 (x + 1 - 1 = x?) but the snake disappears, while the Arraylist keeps the same size (printing it).
The function to calculate the position of the snake (I think that is causing it):
private void move() {
System.out.println(position.size());
Point toAdd = position.get(position.size() - 1);
position.remove(0);
if(dir == 1)
toAdd.y -= 5;
else if(dir == 2)
toAdd.x -= 5;
else if(dir == 3)
toAdd.x += 5;
else if(dir == 4)
toAdd.y += 5;
if(toAdd.x < 0) toAdd.x = 150;
else if(toAdd.x > 150) toAdd.x = 0;
if(toAdd.y < 0) toAdd.y = 150;
else if(toAdd.y > 150) toAdd.y = 0;
position.add(toAdd);
}
But, to make it a Short, Self Contained, Correct Example:
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.*;
import java.util.ArrayList;
class Snake extends JPanel implements Runnable {
int x,y;
boolean horizontal;
ArrayList<Point> position = new ArrayList<Point>();
byte dir = 3;
public Snake(JFrame parent) {
for(int i = 0; i < 5; i++)
position.add(new Point(i*5 + 10, 10));
parent.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
byte change = dir;
switch (e.getKeyCode()) {
case KeyEvent.VK_DOWN:
change = 4;
break;
case KeyEvent.VK_UP:
change = 1;
break;
case KeyEvent.VK_LEFT:
change = 2;
break;
case KeyEvent.VK_RIGHT:
change = 3;
break;
}
changeDirection(change);
}
});
System.out.println("starting thread");
new Thread(this).start();
}
private void changeDirection(byte change) {
if(change != dir && (change - 2 != dir || change + 2 != dir)) {
dir = change;
}
}
public void run() {
for(int i = 0; i != -1; i++){
try {
move();
this.repaint();
Thread.sleep(1000);
}
catch (InterruptedException e) {
System.out.println("INTERRUPTED");
}
}
}
private void move() {
System.out.println(position.size());
Point toAdd = position.get(position.size() - 1);
position.remove(0);
if(dir == 1)
toAdd.y -= 5;
else if(dir == 2)
toAdd.x -= 5;
else if(dir == 3)
toAdd.x += 5;
else if(dir == 4)
toAdd.y += 5;
if(toAdd.x < 0) toAdd.x = 150;
else if(toAdd.x > 150) toAdd.x = 0;
if(toAdd.y < 0) toAdd.y = 150;
else if(toAdd.y > 150) toAdd.y = 0;
position.add(toAdd);
}
public void paintComponent(Graphics g) {
g.clearRect(0,0,150,150);
for(Point p : position)
g.drawRect(p.x, p.y, 5, 5);
}
public static void main(String[] args) {
Snake snake;
JFrame f = new JFrame("Snake");
f.setSize(150, 150);
f.add((snake = new Snake(f)));
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setResizable(false);
f.setVisible(true);
}
}
Movement was the first thing I tried to implement, I have not yet come to collision-detection/food, that's not the question here.
My question is:
Why is the snake shrinking while the arraylist isn't and how can I fix it, i.e. stop the snake from disappearing except for the front segment?
Ok. This is simple!
You are changing point that is already in the list position and at the end you add the same point to this list. You end up with more and more the same (by reference) elements with same positions.
You should create new instance of Point and add it to the list.
Point lastPoint = position.get(position.size() - 1);
Point toAdd = new Point(lastPoint.x, lastPoint.y);
The following code is what I've been trying to use for multitouch. Finger one is set correctly and moves around when I drag my finger. Finger two shows up and disappears when I touch and release my finger, but it never moves around. Any idea what's wrong?
I have read developers blog I still do not understand what the issues are.
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK;
int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
int pointerId = event.getPointerId(pointerIndex);
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
if (pointerId == 0)
{
fingerOneDown = 1;
fingerOneX = event.getX(pointerIndex);
fingerOneY = event.getY(pointerIndex);
}
if (pointerId == 1)
{
fingerTwoDown = 1;
fingerTwoX = event.getX(pointerIndex);
fingerTwoY = event.getY(pointerIndex);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_CANCEL:
if (pointerId == 0)
{
fingerOneDown = 0;
fingerOneX = event.getX(pointerIndex);
fingerOneY = event.getY(pointerIndex);
}
if (pointerId == 1)
{
fingerTwoDown = 0;
fingerTwoX = event.getX(pointerIndex);
fingerTwoY = event.getY(pointerIndex);
}
break;
case MotionEvent.ACTION_MOVE:
if (pointerId == 0)
{
fingerOneDown = 1;
fingerOneX = event.getX(pointerIndex);
fingerOneY = event.getY(pointerIndex);
}
if (pointerId == 1)
{
fingerTwoDown = 1;
fingerTwoX = event.getX(pointerIndex);
fingerTwoY = event.getY(pointerIndex);
}
break;
}
return true;
}
Nevermind this. I fixed it. The ACTION.MOVE event always gets zero as the pointerId for some strange reason. Because of this, you always have to recalculate the pointerId within the event as seen below:
case MotionEvent.ACTION_MOVE:
int pointerCount = event.getPointerCount();
for(int i = 0; i < pointerCount; ++i)
{
pointerIndex = i;
pointerId = event.getPointerId(pointerIndex);
Log.d("pointer id - move",Integer.toString(pointerId));
if(pointerId == 0)
{
fingerOneDown = 1;
fingerOneX = event.getX(pointerIndex);
fingerOneY = event.getY(pointerIndex);
}
if(pointerId == 1)
{
fingerTwoDown = 1;
fingerTwoX = event.getX(pointerIndex);
fingerTwoY = event.getY(pointerIndex);
}
}
break;
Hey guys i'm making a maze game and I'm trying to figure out how to make a 2D collision smooth. Currently I have some really bad collision code that I thought up since I haven't done this part yet and it is glitchy and sometimes goes inside the wall then you can't get out.
My code:
public void checkCollision() {
Rectangle player_rectangle = new Rectangle(player.getX(),player.getY(),32,32);
for(Wall wall : walls) {
Rectangle wall_rectangle = new Rectangle(wall.getX(), wall.getY(), 32,32);
if(player_rectangle.intersects(wall_rectangle)) {
if(player.xspeed == 1) {
player.xspeed = 0;
player.x -= 1.2;
} else {
if(player.xspeed == -1) {
player.xspeed = 0;
player.x += 1.2;
}
else
if(player.yspeed == 1) {
player.yspeed = 0;
player.y -= 1;
} else {
if(player.yspeed == -1) {
player.yspeed = 0;
player.y += 1;
}
}
}
}
}
}
What is a better way to do the collision? here is a picture of the types of maps I will have:
EDIT:
New Collision code:
if (player_rectangle.intersects(wall_rectangle)) {
Rectangle intersection = (Rectangle) player_rectangle.createIntersection(wall_rectangle);
if (player.xspeed > 0) {
player.x -= intersection.getWidth();
}
if (player.yspeed > 0) {
player.y -= intersection.getHeight();
}
if (player.xspeed < 0) {
player.x += intersection.getWidth();
}
if (player.yspeed < 0) {
player.y += intersection.getHeight();
}
Print(Integer.toString(intersection.width) + ", " + Integer.toString(intersection.height));
}
Movement Code:
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT) {
xspeed = -1;
} else {
if(key == KeyEvent.VK_RIGHT) {
xspeed = 1;
} else {
if(key == KeyEvent.VK_UP) {
yspeed = -1;
} else {
if(key == KeyEvent.VK_DOWN) {
yspeed = 1;
}
}
}
}
}
Thanks for any help you can give me.
You can use Rectangle.createIntersection(Rectangle).
If the player moves to a positive direction, just subtract the width and height of the resulting Rectangle from his position, if he moves to a negative, add them.
Don't set the speed to zero, this could cause the player to hang.
EDIT
if (playerRectangle.intersects(wallRectangle) {
Rectangle intersection = (Rectangle) playerRectangle.createIntersection(wallRectangle);
if (player.xspeed > 0) {
player.x -= intersection.getWidth();
}
if (player.yspeed > 0) {
player.y -= intersection.getHeight();
}
if (player.xspeed < 0) {
player.x += intersection.getWidth();
}
if (player.yspeed < 0) {
player.y += intersection.getHeight();
}
}
EDIT2
As far as I know, keyPressed is only triggered when you press a key, and not when you release it. Try it like this:
private boolean up, down, left, right;
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KEyEvent.VK_UP) {
up = true;
}
...
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KEyEvent.VK_UP) {
up = false;
}
...
}
// Call this in the mainthread
public void updateMovement() {
if (up) {
player.xspeed = 1;
}
...
}
So in every frame, you update the movement, move the player and then check the collision.