Creating "stick controls" for android game? - java

I'm trying to create a simple Android game, a 2D action shooter which has 2 control sticks (circles) on the screen, the left one is movement control and the right one weapon control. Direction is being controlled by the position of your thumb relative to the circle’s center.
I've been following a tutorial on this site: http://www.kilobolt.com/day-7-creating-an-android-game-from-start-to-finish.html but it only gave me the base to work on. I have no programming experience so I'm quite lost now.
I got the movement working only on TOUCH_DOWN event, the hero moves to about where it should but to change direction I have to lift my thumb and touch the circle again. TOUCH_DRAGGED (or ACTION_MOVE) is broken because if I drag my finger across the circle the character moves really fast. I guess the problem is too many touch events are being handled, but I have no idea how to fix it.
How can I change this so that I can drag my thumb around the circle and the hero will change its direction instantly, and keep its speed constant all the time? Also the speed should be the same no matter how close or far from the center of the circle you touch.
private void updateRunning(List<TouchEvent> touchEvents, float deltaTime) {
int len = touchEvents.size();
for (int i = 0; i < len; i++) {
TouchEvent event = touchEvents.get(i);
if (event.type == TouchEvent.TOUCH_DOWN || event.type == TouchEvent.TOUCH_DRAGGED) {
if (inBounds(event, 50, 300, 150, 150, 'c')) {
ctrl.setX(event.x);
ctrl.setY(event.y);
ctrl.direction();
hero.move(ctrl.getDirX(), ctrl.getDirY());
}
}
if (event.type == TouchEvent.TOUCH_UP) {
if (inBounds(event, 0, 0, 35, 35,'r')) {
pause();
}
hero.stopMove();
}
}
hero.update();
The movement: hero's speedX and speedY are added to hero's centerX and centerY on every hero.update() call.
public void move(float x, float y) {
speedX += x * MOVESPEED;
speedY += y * MOVESPEED;
}
This method that handles the x & y speed. Found it here at stackoverflow, and because touch_down event is working ok, I guess it's doing it's job. Although I feel it's not exactly how it's supposed to be. L_STICK_C is a constant with values of 100 and 350 (center of the circle).
public void direction() {
dir.x = x - L_STICK_C.x;
dir.y = y - L_STICK_C.y;
double hyp = Math.sqrt(dir.x * dir.x + dir.y * dir.y);
dir.x = (float) (dir.x / hyp);
dir.y = (float) (dir.y / hyp);
}

I suggest you look into some game programming tutorials. You usually would not move the character directly from the touch input. You'd set a game state variable once a game loop which would correspond to the position of your thumb inputs. Then you'd only update the hero once per game loop based on those inputs. This lets allows you to keep the game input control code, and hero code separate, and makes it re-usable for other parts of your game.
EDIT:
Based on your code, every time you drag your finger, you generate a bunch of dragged events. So you are adding onto your characters speed for each event. You should probably just be looking at the distance to center and x / y of the input on the last touch event, not all of them.

Related

How to make a player only be able to jump a certain height in Java?

So, for a school project, I've been trying to get a jumping mechanism down. However, the problem I've been having is that the player is able to just float around, rather than having to fall down after reaching a certain jump height.
I have tried many things, including the normal idea of when the up key is pressed, setting jumping equal to true, and then in the actionPerformed method, setting the yVelocity to -4. But, when the jump key is clicked, I record the yPosition at the time, and when the current yPosition is less than the original position - 50, I set the yVelocity equal to 0, and the fallVelocity to 1.
This is the code in my actionPerformed method:
if (jumping) {
if (yPos <= homeY - 50) {
yVel = 0;
fallVel = 1;
falling = true;
jumping = false;
System.out.println("bye");
} else {
yVel = -JUMP_SPEED;
}
}
yPos += yVel + fallVel;
'''
This is the code in the keyPressed method:
if (!jumping && !falling) {
jumping = true;
homeY = yPos;
count = 0;
}
So, I expect the result to be a player that goes up 50 pixels, and then starts falling down. But in the program, the player just sort of keeps on floating, as long as the up key is pressed.
Jumping does not really work properly as an up/down switch imo. The best approach is to use gravity (which is very easy to add).
To add gravity just modify the player velocity each tick. This should be run on a fixed time update loop to make consistent gravity at different frame rates:
// Play with this number for rate of gravity
player.ySpeed -= 4.9; // Gravity = 9.8m/s^2
Then for your jumping just add to the player ySpeed. This will create a natural parabolic jump.
if (jumpWasPressed) {
player.ySpeed += 50; // play with this number for jump height
}
This approach does assume you have a hotbox for your "ground" object to stop the player from falling through the ground

java lwjgl setting the mouses position without changing dx or dy

Hello I am making a 3D game and now that I've started making something that lets the user interact with a mouse I have been a little stuck (well really stuck).
What I'm trying to do is when the user moves the mouse it gets moved back to the centre (or were the coordinates I entered are) without effecting the Mouse.getDX() and Mouse.getDY().
Here is my code for the part were I test for moving the mouse.
public void onMouser(){
yaw+=Mouse.getDX();
pitch-=Mouse.getDY();
Mouse.setCursorPosition(750, 500);
}
Thanks in Advance
public void calculatePitchAndYaw() {
pitch += Mouse.getY() - HEIGHT /2;
yaw += Mouse.getX - WIDTH / 2;
Mouse.setCursorPosition(WIDTH / 2, HEIGHT /2);
}
Try something like this. So you wont turn back to your initial position.
You can't change position of mouse with serCursorPosition without affect the Mouse.getDX();
You can try save vars before change cursos position:
int saveDX = Mouse.getDX();
int saveDY = Mouse.getDY();
Mouse.setCursorPosition(750, 500);
Regards.

Shooting object based on arm rotation in libgdx java

I am trying to shoot an object(a spell) depending on the rotation of the players arm. The spell is supposed to come out of the hand and shoot towards where the mouse cicked(the arm rotates and points to where the mouse is). This is how the arm rotates in game.
public boolean mouseMoved(int screenX, int screenY) {
tmp.x = screenX;
tmp.y = screenY;
tmp.z = 0;
cam.unproject(tmp);
rot = MathUtils.radiansToDegrees * MathUtils.atan2((float)tmp.y - (float)player.getArmSprite().getY() - player.getArmSprite().getHeight(),
tmp.x -player.getArmSprite().getX() - player.getArmSprite().getWidth());
if (rot < 0) rot += 360;
//Last right or left means if hes looking left or right
if(player.lastRight)
player.setObjectRotation(rot + 80);
if(player.lastLeft)
player.setObjectRotation(-rot - 80);
And this is how the spell is supposed to shoot based off rotation
//destination is a vector of where on screen the mouse was clicked
if(position.y < destination.y){
position.y += vel.y * Gdx.graphics.getDeltaTime();
}
if(position.x < destination.x){
position.x += vel.x * Gdx.graphics.getDeltaTime();
}
However this is very wonky and never really reacts the way it supposed to with a few exceptions. It fires from the hand and then if the y axis is equal it completely evens out and goes till it reaches the x position, I want it to fire from the hand to the position clicks perfectly straight from point a to point b, this is clearly a rotation problem that I just can't seem to figure out how to tackle.
Here is an image of what is happening
Example image
The red indicates where I clicked, as you can see it reached the x pos first and now is traveling to the y when it should have reached the x and y pos of where I clicked first
Any help with this problem is extremely appreciated!
I'm pretty bad at radians and tangents but luckily we have vectors.
Since you have the rot ation in degrees of the arm. I advice to use Vectors to use for any Vector related math now.
//A vector pointing up
Vector2 direction = new Vector2(0, 1);
//Let's rotate that by the rotation of the arm
direction.rotate(rot);
Now direction is the direction the arm is pointing. If your rotation is calculated where up = 0. So you might need to rotate it 180, 90 or -90 degrees. Or in the case you did something silly any degrees.
Your spell should have a Vector too for it's position. Set that to the hand or wherever you want to start from. Now all you need to do is scale that direction since it's currently has a length of 1. If you want to move 5 units each frame you can do direction.scl(5) now it is of length 5. But technically speaking it's no direction anymore now everybody calls it velocity so let's do.
//when you need to fire
float speed = 5;
Vector2 velocity = direction.cpy().scl(speed);
//update
position.add(velocity);
draw(fireballImage, position.x, position.y);
I copied direction first, otherwise it would also be scaled. Then I just added the velocity to the position and draw using that Vector.
And to show Vectors are awesome you should see this awesome badlogic vs mouse program I created. https://github.com/madmenyo/FollowMouse there are just a view lines of my own code. It just takes a little bit of vector knowledge and it's very readable.

Bring Ball To A Stop

I have the following methods in my program which keep a ball continuously bouncing. I have tried modifying but can't seem to get the ball to stop at the bottom of my GUI. My main goal is to have the methods simulate as if you were bouncing a real ball.
private void updateDelta() {
final int minimumMovement = 5;
final int maxExtra = 10;
deltaY = minimumMovement + (int) (Math.random() * maxExtra);
}
public void verticalBounce(Container container) {
// controls vertical ball motion
if (upDown) {
y += deltaY;
if (y >= getHeight()) {
upDown = false;
updateDelta();
}
} else {
y += -deltaY;
if (y <= 0) {
upDown = true;
updateDelta();
}
}
}
UPDATE:
Ball bounces and stops at the bottom of the gui.
public void verticalBounce(Container container) {
deltaY = deltaY - gravity;
y = y + deltaY;
if (y > getHeight()) {
y = getHeight(); // reset location
deltaY = (int) (deltaY * -0.9); // slows down ball
}
}
None of that code looks correct. You need to implement the equation(s) of rectilinear motion:
http://en.wikipedia.org/wiki/Linear_motion
The one you need is s = ut + 0.5 * a * t * t, where
s = distance
u = an initial velocity - regard as the speed at which it hits the ground
a = acceleration due to gravity (you can probably have this pretty arbitrary)
t = time
You reverse the sign of a on the way up.
To simulate lossy bouncing, reduce u by taking a certain factor of energy E out of the system:
new_u * new_u = (1 - E)u * u.
(This comes from the formula for the kinetic energy of a moving body).
I can see from your question that you are capable of implementing this, so I won't provide code; just the physics.
First, a bouncing ball doesn't have a random element in it. Its all determined by the forces acting on the ball and the speed and direction of the ball. If you add a little randomness, it may make it look a little more realistic because of things like wind and unbalance in the ball but its very little.
To program it, assume the ball gets shot up from the ground at some speed. You need to store:
Y = location in units above the ground. Start at 0.
deltaY = speed in units per time interval. Negative is down. Positive is up. Start at 10.
gravity = acceleration in units of change per time interval. Gravity is always negative and constant. Start with -2 and try some values.
Unless you want the ball to disappear off the screen as it reaches the top of the bounce, you will need to select a ceiling height. Say 100. (Which is best chosen to match your graphics area's height, though.)
So for every time interval/tick/loop you do the following:
Adjust for gravity by subtracting gravity from deltaY. (If the ball is moving down it will move faster. If its moving up, it will move slower.)
Move the ball by adding deltaY to Y.
Then you have to check: Did the ball hit the ground or the ceiling? Is Y greater than the ceiling value or less than the ground one (0).
If so, you have to bounce it by:
Move Y such that if it was X past the boundary (ground/ceiling) it becomes X within the boundary. (If Y = 110 and ceiling = 100, set Y to 90. If Y = -5, set it to +5.)
Negate deltaY. In a bounce the direction reverses. (deltaY = -deltaY)
Reduce deltaY by a percentage. Some energy is lost in the bounce so speed is slower after a bounce. (deltaY = deltaY * 0.90 or some other amount) #Bathsheba calls that removing energy from the system.
That's all there is to it. You have to fiddle with the numbers to make it take off at a reasonable speed. You have to adjust the time interval. You don't have to match real life. Just do what looks good.
As time goes by, the speed will reduce to 0.
(And despite what I said before, adding or subtracting a small random amount actually looks kind of cool.)
Your ball is bouncing randomly instead of slowly decreasing in velocity. You need to lower your velocity every bounce until the velocity is under minimumMovement then make the velocity 0 and stop bouncing.

Continuous movement after touch?

Found plenty of questions that were similar, but nothing that answers my own problem. It's probably something really bloody simple, but it's late and I can't fathom it. I've got an android game I'm working on, where you touch the screen and it 'fires' a sprite in that direction. I've got most of the code working, however, after the sprite fires and moves off, it gets to the touch point and then just wiggles. I would like it to carry on along that angle and eventually bounce around...
Here's my code (well the bits that matter):
List<TouchEvent> touchEvents = game.getInput().getTouchEvents();
int len = touchEvents.size();
for(int i = 0; i < len; i++) {
TouchEvent event = touchEvents.get(i);
if(event.type == TouchEvent.TOUCH_UP) {
touchPoint.set(event.x, event.y);
guiCam.touchToWorld(touchPoint);
}
}
//Log.d("PANDAM", touchPoint.x + "|" + touchPoint.y);
float speed = 112f;
double theta = 180.0 / Math.PI * Math.atan2(panda_y - touchPoint.y, panda_x - touchPoint.x);
Log.d("PANDAM", " > "+theta+" < ");
movePanda(theta, speed, deltaTime);
And the "movePanda" method:
private void movePanda(double angle, float speed, float deltaTime)
{
panda_x += speed * Math.cos(angle)*deltaTime;
panda_y += speed * Math.sin(angle)*deltaTime;
}
My question is, how do I get the panda to carry on along the touch vector and not spaz out when it reaches the original touch point?
You seem to be recalculating the angle each step of the animation, but you actually need to remember what the angle was when you first started moving. As you pass the original touch point, the angle changes to point the other direction, so if you reclcalculate it every animation step, it will change and eventually point the other way.

Categories