I'm writing a little program for a school project. The theme is "objective Coding" so there's the "main Tab" where the draw method and setup method is. In other tabs, I wrote other classes and functions.
So in the my "main Tab" there's the function void draw and it looks like this:
void draw() {
background();
h1.displayH();
steuerungH();
t1.displayT();
}
The three methods background();, h1.displayH(); and t1.displayT(); worked without a problem. I tried writing the code like:
...
...
h1.streuerungH();
...
h1 is an object, a rectangle I try to move with the function void steuerungH();, but there's always an error saying:
The function steuerungH() does not exist.
Im not sure what the problem exactly is, because the class in which I wrote the function void steuerungH(); looks exacltly like the others
float gravity = 0.1;
float speed = 0;
class Steuerung {
void steuerungH(){
if (key == UP|| key == 'w') {
playerYPosition = playerYPosition +speed;
speed = speed + gravity;
if (playerYPosition >= 30); {
speed = speed *-1;
}
} else if (key == DOWN ||key == 's') {
/*Duck methode muss noch geschrieben werden*/
} else if (key == RIGHT || key == 'd') {
playerXPosition = playerXPosition +10;
} else if (key == LEFT ||key == 'a') {
playerXPosition = playerXPosition -10;
}
}
}
First of all you should think about playerXPosition and playerYPosition. Wouldn't it be better to create a class Player with the attributes playerXPosition and playerYPosition and a method streuerungH?
class Player {
float gravity = 0.1;
float speed = 0;
float playerXPosition;
float playerYPosition;
// [...]
void steuerungH(){
if (key == UP|| key == 'w') {
playerYPosition = playerYPosition +speed;
speed = speed + gravity;
if (playerYPosition >= 30); {
speed = speed *-1;
}
} else if (key == DOWN ||key == 's') {
/*Duck methode muss noch geschrieben werden*/
} else if (key == RIGHT || key == 'd') {
playerXPosition = playerXPosition +10;
} else if (key == LEFT ||key == 'a') {
playerXPosition = playerXPosition -10;
}
}
}
Anyway, if you want to keep your current designe, then you have to options to solve the issue:
Create an instance of Steuerung. e.g.
Steuerung s = new Steuerung();
void draw() {
// [...]
s.streuerungH();
// [...]
}
The other option is:
Since Processing provides functions in global namespace, you can turn steuerungH to a function:
float gravity = 0.1;
float speed = 0;
void steuerungH(){
// [...]
}
void draw() {
// [...]
streuerungH();
// [...]
}
You have to create a new Steuerung object like this
Steuerung steuerung = new Steuerung();
Then you can call the method with
steuerung.steuerungH();
When you simply do
steuerungH();
Java will be looking for a steuerungH() method in your Main class which doesn't exist and therefor throws an error.
Related
I am programming a little game. So far I have a player, who can move in a 2D printed tile world following the player. Here a small preview.
Right now my player movement code looks like this:
KeyListener class
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
for(int i = 0; i < handler.object.size(); i++){
GameObject tempObject = handler.object.get(i);
if(tempObject.getId() == ID.Player){
if(key == KeyEvent.VK_D) tempObject.setVelX(5);
if(key == KeyEvent.VK_A) tempObject.setVelX(-5);
if(key == KeyEvent.VK_SPACE && Var.jump == true) {
tempObject.setVelY(-10);
Var.jump = false;
}
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
for(int i = 0; i < handler.object.size(); i++){
GameObject tempObject = handler.object.get(i);
if(tempObject.getId() == ID.Player){
if(key == KeyEvent.VK_D) tempObject.setVelX(0);
if(key == KeyEvent.VK_A) tempObject.setVelX(0);
}
}
Player class
public void tick() {
if (Var.falling == true) {
velY += Var.gravity;
if (velY > 10) {
velY = 10;
}
}
x += velX;
y += velY;
These codes are just parts of the classes.
Problem
When I am moving to the right or to the left with A or D and then tap the other key (from a to d/ from d to a) in a certain way, my character stands still for a short time and then moves after this short delay. See here.
User presses D, which triggers a call to keyPressed, which calls tempObject.setVelX(5).
User releases A, which triggers a call to keyReleased, which calls tempObject.setVelX(0). This halts your character’s motion.
User is still holding down D, so after a short delay, that key’s autorepeat triggers another call to keyPressed, which causes tempObject.setVelX(5) to be called again, causing the character to start moving again.
You should not be calling tempObject.setVelX(0) unless no movement key is pressed.
How do you determine that? You need to define instance fields which keeps track of them. For example:
private boolean leftPressed;
private boolean rightPressed;
// ...
public void keyPressed(KeyEvent e) {
//...
if (key == KeyEvent.VK_D) {
rightPressed = true;
tempObject.setVelX(5);
}
if (key == KeyEvent.VK_A) {
leftPressed = true;
tempObject.setVelX(-5);
}
//...
}
public void keyReleased(KeyEvent e) {
//...
if (key == KeyEvent.VK_D) {
rightPressed = false;
if (!leftPressed) {
tempObject.setVelX(0);
}
}
if (key == KeyEvent.VK_A) {
leftPressed = false;
if (!rightPressed) {
tempObject.setVelX(0);
}
}
//...
}
Some side notes:
gameObject would be a much better variable name than tempObject.
You should never write “booleanVariable == true”. Instead, just write booleanVariable. This avoids any possibility of an accidental assignment by writing one ‘=’ instead of two. For instance:
if (Var.falling) {
Put more simply: remove every occurrence of == true from your code.
It's hard to say what the exact problem is without knowing the exact sequence of keyups and keydowns, but it looks as if your program is vulnerable to overlapping keyup/keydown sequences - for example:
A down -> velocity = -5
D down -> velocity = +5
A up -> velocity = 0 // but you want it to still be +5
Add logging to your game code to help debug these situations.
There are a number of ways to handle this, but one way is to keep a running count of currently-down keys:
public void keyPressed(KeyEvent e) {
heldKeys++;
... other code ...
}
public void keyReleased(KeyEvent e) {
heldKeys--;
... other code ...
if(heldKeys == 0) {
velocity = 0;
}
}
This is lightweight but blunt. A more refined approach might be to keep a record of the state of each key:
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
heldKeys.set(key, true);
}
... do your game state updates on the basis of what's in keyStates.
Depending on how fanatical you want to get about efficiency, keyStates could be a HashSet(Integer, Boolean) or something more specialised of your own creation.
BUT! See How to know when a user has really released a key in Java? for discussion on auto-repeat from the keyboard.
So I made a Pong game in java and for some reason sometimes the ball doesn't check the collision with the bottom or the top of the screen. What can I do to fix this?
this piece is the collision checking with the bottom or the top of the screen:
if(y-20<0 && dir == UP_RIGHT)
dir=DOWN_RIGHT;
else if (y-20<0 && dir == UP_LEFT)
dir=DOWN_LEFT;
//Down
if(y+20>500 && dir == DOWN_RIGHT)
dir=UP_RIGHT;
else if(y+20>500 && dir == DOWN_LEFT)
dir=UP_LEFT;`
The ball collision system:
public void Blogic(Random random,HumanPaddle p1, HumanPaddle p2)
{//collision
//Left
if(x<=50)
{
if(y>= p1.y && y<=p1.y + 80)
RandomDir(6,4,random);
}
//Right
else if(x>=650)
{
if(y>=p2.y && y<=p2.y+ 80)
RandomDir(3,1,random);
}
//Up
if(y-20<0 && dir == UP_RIGHT)
dir=DOWN_RIGHT;
else if (y-20<0 && dir == UP_LEFT)
dir=DOWN_LEFT;
//Down
if(y+20>500 && dir == DOWN_RIGHT)
dir=UP_RIGHT;
else if(y+20>500 && dir == DOWN_LEFT)
dir=UP_LEFT;
}
The ball movement system:
public void move()
{
switch(dir)
{
case STOP:
xVel *=0; yVel *=0;
break;
case LEFT:
xVel--;
break;
case UP_LEFT:
xVel--;
yVel--;
break;
case DOWN_LEFT:
xVel--;
yVel++;
break;
case RIGHT:
xVel++;
break;
case UP_RIGHT:
xVel++;
yVel--;
break;
case DOWN_RIGHT:
xVel++;
yVel++;
break;
default:
break;
}
// Velocity settings
if (xVel>=3)
xVel=3;
else if (xVel <=-3)
xVel=-3;
if(yVel >=3)
yVel=3;
else if(yVel<=-3)
yVel=-3;
x += xVel;
y += yVel;
}
Run:
public void run()
{
for (;;)
{
p1.move();
p2.move();
ball.move();
ball.Blogic(rand, p1, p2);
Score();
repaint();
try
{
Thread.sleep(10);
}
catch (InterruptedException ex)
{
Logger.getLogger(Tennis.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
I'm having a hard time seeing exactly how the collision works without the visual but I would try without the extra checking on the direction for the up and bottom boards. I believe that by doing this you are checking for something that should ways be true anyways so it is simply too strict.
Remove: "&& dir == UP_RIGHT" and the contrary.
For some reason, this might not be true and completely skip over the check.
I made this changes inside that piece and now it is working fine.
if(y <=10)
{
if(dir == UP_RIGHT) dir=DOWN_RIGHT;
else if (dir == UP_LEFT)dir = DOWN_LEFT;
else yVel=-yVel;
}
//Down
if(y>=490)
{
if(dir == DOWN_RIGHT)dir=UP_RIGHT;
else if (dir ==DOWN_LEFT) dir=UP_LEFT;
else yVel=-yVel;
}
Currently I have a game that I am building in Netbeans, and have been able to create a board, place the pieces and allow them to be moved anywhere using mouseveent's
But now I have ran into a problem when trying to code the pieces on the board to only do allowed actions.
The problem I am having is that every piece is still allowed to be moved but now when it is moved the selected piece disappears from the board completely ingorning all the new function in the mouse release event
The code I am trying to add is for the WhitePawn which is the only piece that should be allowed to move right now
The rest if they are tried to move should just return to there set positions regardless of where they are dragged. I have removed all code not relevant to the question and ran the debugger. From that I know a fact that the problem is somewhere in the mouse release event code, I just cant find it.
public void mouseReleased(MouseEvent e) {
if (chessPiece == null) {
return;
}
chessPiece.setVisible(false);
Boolean success = false;
Component c = chessBoard.findComponentAt(e.getX(), e.getY());
String tmp = chessPiece.getIcon().toString();
String pieceName = tmp.substring(0, (tmp.length() - 4));
Boolean validMove = false;
//Pawn Moves
//White Pawn
if (pieceName.equals("WhitePawn")) {
if (startY == 1) {
if ((startX == (e.getX() / 75)) && ((((e.getY() / 75) - startY) == 1) || ((e.getY() / 75) - startY) == 2)) {
if ((((e.getY() / 75) - startY) == 2)) {
if ((!piecePresent(e.getX(), (e.getY()))) && (!piecePresent(e.getX(), (e.getY() + 75)))) {
validMove = true;
} else {
validMove = false;
}
} else {
if ((!piecePresent(e.getX(), (e.getY())))) {
validMove = true;
} else {
validMove = false;
}
}
} else {
validMove = false;
}
} else {
int newY = e.getY() / 75;
int newX = e.getX() / 75;
if ((startX - 1 >= 0) || (startX + 1 <= 7)) {
if ((piecePresent(e.getX(), (e.getY()))) && ((((newX == (startX + 1) && (startX + 1 <= 7))) || ((newX == (startX - 1)) && (startX - 1 >= 0))))) {
if (checkWhiteOponent(e.getX(), e.getY())) {
validMove = true;
if (startY == 6) {
success = true;
}
} else {
validMove = false;
}
} else {
if (!piecePresent(e.getX(), (e.getY()))) {
if ((startX == (e.getX() / 75)) && ((e.getY() / 75) - startY) == 1) {
if (startY == 6) {
success = true;
}
validMove = true;
} else {
validMove = false;
}
} else {
validMove = false;
}
}
} else {
validMove = false;
}
}
}
if (!validMove) {
int location = 0;
if (startY == 0) {
location = startX;
} else {
location = (startY * 8) + startX;
}
String pieceLocation = pieceName + ".png";
pieces = new JLabel(new ImageIcon(getClass().getResource(pieceLocation)));
panels = (JPanel) chessBoard.getComponent(location);
panels.add(pieces);
} else {
if (success) {
int location = 56 + (e.getX() / 75);
if (c instanceof JLabel) {
Container parent = c.getParent();
parent.remove(0);
pieces = new JLabel(new ImageIcon(getClass().getResource("WhiteQueen.png")));
parent = (JPanel) chessBoard.getComponent(location);
parent.add(pieces);
} else {
Container parent = (Container) c;
pieces = new JLabel(new ImageIcon(getClass().getResource("WhiteQueen.png")));
parent = (JPanel) chessBoard.getComponent(location);
parent.add(pieces);
}
} else {
if (c instanceof JLabel) {
Container parent = c.getParent();
parent.remove(0);
parent.add(chessPiece);
} else {
Container parent = (Container) c;
parent.add(chessPiece);
}
chessPiece.setVisible(true);
}
}
}
Image showing the folder layout of My build in case I have you can see somewhere that is not linked probably
Hopefully someone can see where I am going wrong, as I just want to get one piece moving before I split the pieces away from the board.java file completely into a new java file
I've looked through some of your code, again there's too much for me to go through in its entirety, but please let me give you some suggestions.
This is brittle/dangerous code:
JLabel awaitingPiece = (JLabel) c1;
String tmp1 = awaitingPiece.getIcon().toString();
if (((tmp1.contains("White")))) {
You're using an object's toString() representation as part of your code logic which is something you should never do. You're also doing String manipulations on the String returned, and again using the returned String for code logic,
Component c = chessBoard.findComponentAt(e.getX(), e.getY());
String tmp = chessPiece.getIcon().toString();
String pieceName = tmp.substring(0, (tmp.length() - 4));
Boolean validMove = false;
again something that is dangerous to do.
Instead, you could get the Icon and compare for Icon equality via the equals(...) method. Even better though is to get your logic out of your GUI and into the Model section of your program. If you can fully separate concerns, you'll stand a much better chance of having smaller units of code that are much easier to debug for both you and for us.
Otherwise, to get a better more complete answer, you're still going to want to first work to isolate the error, and for that, I still recommend that you use an MCVE.
Also I see that you're checking if an Icon is named "WhitePawn"
chessPiece.setVisible(false);
Boolean success = false;
Component c = chessBoard.findComponentAt(e.getX(), e.getY());
String tmp = chessPiece.getIcon().toString();
String pieceName = tmp.substring(0, (tmp.length() - 4));
Boolean validMove = false;
//Pawn Moves
//White Pawn
if (pieceName.equals("WhitePawn")) {
When in actuality I'll bet that it's named something quite differently. Since your Strings are playing a key role in your program (too great a role, I fear) are you debugging your String values to see why the code doesn't work?
For instance, a few println's could do wonders:
chessPiece.setVisible(false);
Boolean success = false;
Component c = chessBoard.findComponentAt(e.getX(), e.getY());
String tmp = chessPiece.getIcon().toString();
String pieceName = tmp.substring(0, (tmp.length() - 4));
System.out.println("pieceName is: " + pieceName); // ******* Added ********
Boolean validMove = false;
Myself, I'd not use Strings for this but rather would use enums, something you know will be stable and will be exactly what you assume it to be.
#Override
public boolean onTouchEvent(MotionEvent event)
{
synchronized (getHolder())
{
int aktion = event.getAction();
if (aktion == MotionEvent.ACTION_DOWN)
{
touched = true;
bar.shareTouch(event.getX(), event.getY(), touched);
}
else if (aktion == MotionEvent.ACTION_UP)
{
touched = false;
bar.shareTouch(event.getX(), event.getY(), touched);
}
if (aktion == MotionEvent.ACTION_POINTER_DOWN)
{
touched2 = true;
bar.shareTouch2(event.getX(), event.getY(), touched2);
}
else if (aktion == MotionEvent.ACTION_POINTER_UP)
{
touched2 = false;
bar.shareTouch2(event.getX(), event.getY(), touched2);
}
}
return true;
}
This is a Code to chech if first Finger is going onto the screen or leaving it. The same for another finger.
public void shareTouch2(float xTouch2, float yTouch2, boolean touched2)
{
if (xTouch2 <= gameViewWidth/2) {
if (touched2 == true) {
touchedLeft2 = true;
}
else if(touched2 == false) {
touchedLeft2 = false;
}
}
else if (xTouch2 > gameViewWidth/2) {
if (touched2 == true) {
touchedRight2 = true;
}
else if(touched2 == false) {
touchedRight2 = false;
}
}
}
public void shareTouch(float xTouch, float yTouch, boolean touched)
{
if (xTouch <= gameViewWidth/2) {
if (touched == true) {
touchedLeft = true;
}
else if(touched == false) {
touchedLeft = false;
}
}
else if (xTouch > gameViewWidth/2) {
if (touched == true) {
touchedRight = true;
}
else if(touched == false) {
touchedRight = false;
}
}
}
private void moveRight()
{
x += 3;
}
private void moveLeft()
{
x -= 3;
}
private void checkTouch() {
if ((touchedLeft == true && touchedRight2 == false) || (touchedLeft2 == true && touchedRight == false)) {
moveLeft();
}
else if ((touchedLeft == false && touchedRight2 == true) || (touchedLeft2 == false && touchedRight == true)) {
moveRight();
}
else if ((touchedLeft == true && touchedRight2 == true) || (touchedLeft2 == true && touchedRight == true)) {
}
}
The checkTouch() is called in the onDraw() Method. Now if I place a finger on the right side of the screen it moves right. Same for left. But if I touch left and the right without removing the left finger the Object still moves left although it should stop. Now when I leave the left finger it still moves left although it should move right.
I hope you understand my problem.
Hope you can help
You can't just assume the ACTION_POINTER_UP Event will only be sent for the same finger ACTION_POINTER_DOWN was sent.
Just as the ACTION_DOWN event is always fired for the first finger to touch down, the ACTION_UP event is only fired for the last finger to lift (i.e. when there are no more fingers on the screen). All others will get an ACTION_POINTER_UP event, even if it's the finger that started the gesture.
However, the Android documentation does specify
Each pointer has a unique id that is assigned when it first goes down [and] remains valid until the pointer eventually goes up.
So in theory, your first and second finger should still have the same ID, regardless whether the Event that reports them.
The solution is simple, then: Use getPointerCount() and getPointerID() to keep track of your fingers.
This may be easier if you refactor your code to account for more than two fingers by replacing the Booleans touchedLeft and touchedLeft2 with a single counter, e.g. fingersOnLeftSide - which has the neat side effect of only needing one shareTouch() method and otherwise reducing redundancy in your code.
EDIT:
Disclaimer: This is just off the top of my head, untested and written without knowledge of any of your code other than what you posted. Not necessarily the best way to solve your problem, but the shortest I could think of.
This is the Event handler:
public boolean onTouchEvent(MotionEvent event)
{
synchronized (getHolder())
{
int aktion = event.getAction();
if (aktion == MotionEvent.ACTION_DOWN || aktion == MotionEvent.ACTION_POINTER_DOWN
|| aktion == MotionEvent.ACTION_UP || aktion == MotionEvent.ACTION_POINTER_UP)
{
bar.clearTouches();
for (int i = 0; i < event.getPointerCount(); i++) {
bar.shareTouch(event.getX(i)); // we don't need the y coordinate anyway
}
}
}
return true;
}
The rewritten shareTouch() to go along with it, as well as clearTouches() I introduced to make this simpler:
private void shareTouch(float x)
{
if (x < gameViewWidth/2) {
fingersLeft++;
} else {
fingersRight++;
}
}
private void clearTouches()
{
fingersLeft = 0;
fingersRight = 0;
}
And finally, the new checkTouch():
public void checkTouch()
{
if (fingersLeft > fingersRight) {
moveLeft();
} else if (fingersRight > fingersLeft) {
moveRight();
}
}
Im doing a pacman game. The following code is for ghosts movement and it works correctly. But I have to include a another check. The problem is that I always ruin the logic.
Current code:
public void moveGhost(Tiles target) {
if(specialIntersections()){
direction = direction; //keeps going in the same direction
}
else{
int oppDir;
if(direction == UP){
oppDir = DOWN;
}
else if(direction == DOWN){
oppDir = UP;
}
else if(direction == LEFT){
oppDir = RIGHT;
}
else{
oppDir=LEFT;
}
double minDist = 10000.0;
Tiles potentialNext;
for(int i=0; i<4; i++){
if(i!=oppDir){
potentialNext = maze.nextTile(getCurrentPos(), i);
if(!(potentialNext.wall()) && check(potentialNext)){
if(calculateDistance(target, potentialNext) < minDist){
minDist = calculateDistance(target, potentialNext);
futureDirection = i;
}
}
}
}
}
changeDirection();
timer++;
increment();
x += xinc;
y += yinc;
tunnel();
}
Another check I need to include:
//if the door is a wall (closed) the object cannot go through it
if(DoorIsWall()){
if(!(potentialNext.wall()) && !(potentialNext.door()) && check(potentialNext)){
I generally write a new method when my conditions start to get unruly:
if (isTileValid(potentialNext)) {
// do stuff
}
private boolean isTileValid(TileObject someTile) {
if (someTile.wall()) {
return false;
}
if (someTile.door()) {
return false;
}
if (! check(someTile)) {
return false;
}
return true;
}