Shape increases in size instead of moving - Java (GUI applet) - java

I am trying to change the y position of the rectangle, however, whenever I try to, it expands/gets bigger vertically.
public class PlayerPaddle implements Paddle {
double yVelocity;
final double GRAVITY = 0.94;
//move up/down faster (if not accelerating = slow down)
boolean upAccel, downAccel;
//determines if player 1 or player 2 (on left or on right)
int player;
//position of actual paddle
int x;
double y;
Rectangle panel;
public PlayerPaddle(int player) {
upAccel = false;
downAccel = false;
y = 210; //not moving initially
yVelocity = 0;
if (player == 1) {
//left side
x = 20;
} else {
//right side
x = 660;
}
}
#Override
public void draw(Graphics g) {
//draw paddle
g.setColor(Color.WHITE);
g.fillRect(x, (int) y, 20, 80);
}
#Override
public void move() {
if (upAccel) {
yVelocity -= 2;
} else if (downAccel) {
yVelocity += 2;
} else if ((!upAccel) && (!downAccel)) {
yVelocity *= GRAVITY;
}
y += yVelocity; //changes y position of paddle
}
public void setUpAccel(boolean input) {
upAccel = input;
}
public void setDownAccel(boolean input) {
downAccel = input;
}
#Override
public int getY() {
return (int) y;
}
}
I want to know how to make the rectangle move up and down vertically. A similar question had only one answer which said that the previously painted rectangle was not being cleared and as a result is expanding. But even when I say g.clearRect(...) it still expands and does not move.
I am new to Swing and Awt but I am really committed to learning. Thanks for the help.

A similar question had only one answer which said that the previously painted rectangle was not being cleared and as a result is expanding
And that is still probably the problem here.
Somewhere, not in the code presented here, you need to invoke the draw(...) method of this class.
So in that code you need to make sure the background of the component is cleared before you draw the paddle. Since you should be overriding the paintComponent(...) method of a panel to do custom painting your code should look something like:
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
// draw the paddle
}
Read the section from the Swing tutorial on Custom Painting for more information and working examples.
I am new to Swing and Awt but I am really committed to learning.
Then keep a link to the tutorial handy for all Swing basics.

Related

I cannot figure out a way to move the balls

I am currently working on a 3 cushion billiards game project. I have added two balls on the table so far. I am trying to move one of the balls but I am having a hard time doing that. Should I use a timer? If so then could you tell me an effective way to use the timer on my code so I can move my balls?
Your help would be much appreciated.
Thanks in advance.
Farhan Hasan
I have tried to create a move function for the class balls. But I am not sure what I should put inside the function, I have added the xSpeed and ySpeed. The xLocation and the yLocation changes depending on the xSpeed and ySpeed.
public class Balls
{
private Color ballFillColor;
private Color ballBorderColor;
private int ballX = 0;
private int ballY = 0;
private int xSpeed = 5;
private int ySpeed = 0;
private int ballWidth = 0;
private int ballHeight = 0;
Timer t;
public boolean fillBall = false;
private static Balls ballArray[]; //Required for drawMultipleBalls
Balls(){ //Constructor
ballBorderColor = Color.black;
}
Balls(int ballX, int ballY, int ballWidth, int ballHeight, Color ballBorderColor, JFrame window){ //Constructor
// X , Y , Width, Height, Border Colour, container
this.setBallBorderColor(ballBorderColor);
this.setBallWidth(ballWidth);
this.setBallHeight(ballHeight);
this.setBallX(ballX);
this.setBallY(ballY);
this.drawBall(window);
}
//Here is the move function. I am not really sure what to do here.
public void move()
{
if(this.ballX < 1000 - this.ballWidth)
{
this.ballX += this.xSpeed;
}
try
{
Thread.sleep(1);
}
catch(Exception e)
{
}
}
//GET AND SET FUNCTIONS HERE
//HERE ARE THE FUNCTIONS WHICH ARE RESPONSIBLE FOR DRAWING MY BALLS IN JFRAME
public void drawBall(JFrame frame)
{
frame.getContentPane().add(new MyComponent());
}
public void drawMultipleBalls(JFrame frame, Balls[] balls)
{
ballArray = balls;
frame.getContentPane().add(new MyComponent2());
}
private class MyComponent extends JComponent{
public void paintComponent(Graphics g){
if (fillBall) //Fill first, and then draw outline.
{
g.setColor(ballFillColor);
g.fillOval(getBallX(),getBallY(), getBallHeight(),getBallWidth());
}
g.setColor(getBallBorderColor());
g.drawOval(getBallX(),getBallY(), getBallHeight(),getBallWidth());
}
}
private class MyComponent2 extends JComponent{
public void paintComponent(Graphics g){
for (int i = 0; i < ballArray.length; i++)
{
if (ballArray[i].fillBall) //Fill first, and then draw outline.
{
g.setColor(ballArray[i].ballFillColor);
g.fillOval(ballArray[i].getBallX(),ballArray[i].getBallY(), ballArray[i].getBallHeight(),ballArray[i].getBallWidth());
}
g.setColor(ballArray[i].getBallBorderColor());
g.drawOval(ballArray[i].getBallX(),ballArray[i].getBallY(), ballArray[i].getBallHeight(),ballArray[i].getBallWidth());
}
}
}
Hopefully, I can have two movable balls for the game, the should bounce back as the hit the edge of the screen and they should be able to slow down over time. For that, I am thinking to use a damper (I will multiply the xSpeed and ySpeed with a number less than 1, eventually it will slow down the ball)
Here is a simple example I came up with to show a ball moving and bouncing off the edges.
The direction changes based on the boundary. Left and top edges just check for 0. Bottom and right edges need to include the diameter of the ball.
The x and y increments are independent. And these amounts in conjunction with the timer can change the movement. Notice however, that to have objects bounce off of each other (as in a pool game) is more complicated due to angle of trajectories, etc. And the distances bounced will vary and slow with time based on frictional values. Everything else is documented in the Java API.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MovementDemo extends JPanel implements ActionListener {
JFrame frame = new JFrame("Movement Demo");
int size = 500;
int x = 50;
int y = 200;
int diameter = 50;
int yinc = 2;
int xinc = 2;
int xdirection = 1;
int ydirection = 1;
public MovementDemo() {
setPreferredSize(new Dimension(size, size));
frame.add(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new MovementDemo().start());
}
public void start() {
Timer timer = new Timer(100, this);
timer.setDelay(5);
timer.start();
}
public void actionPerformed(ActionEvent ae) {
if (x < 0) {
xdirection = 1;
}
else if (x > size - diameter) {
xdirection = -1;
}
if (y < 0) {
ydirection = 1;
}
else if (y > size - diameter) {
ydirection = -1;
}
x = x + xdirection * xinc;
y = y + ydirection * yinc;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.BLUE);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillOval(x, y, diameter, diameter);
}
}
It seems in general there are a few things you need to figure out:
has the ball collided with another ball
has the ball collided with a wall
otherwise just figure out what is the ball's new position based on its velocity
Below is some sample code that stubs some of this out. You can first compare the current ball's position to all others (not including the current ball of course). If there are any equal positions, process a collision with a ball. If the ball is at the window border i.e it hit a wall, process a collision with a wall. Otherwise just calculate its new position based on its current velocity.
The process collision part is just to apply physics mechanics to whatever degree of complexity you require. One general suggested change would be to update the velocity of the balls then apply it to the position after. The specific calculations for velocity changes you could apply as needed and as you can imagine it can get pretty involved which is why I suggest using a separate method and possibly a sub class for velocity instead of managing each part of the velocity vector in the ball itself. I used the wall as an object because of this. The composition, weights, velocities etc of the object's colliding can affect the resulting collision, but how complex you want that processing to be is up to you.
Sorry I'm no physics expert but I hope this sends you in the right direction in terms of code! Also this might help with the specific calculations you might want to use:
https://www.khanacademy.org/science/physics/one-dimensional-motion/displacement-velocity-time/v/calculating-average-velocity-or-speed
public void move()
{
// check if balls are on same position not including this ball
for(Ball b: ballArray){
if (this.position == b.position && this != b){
processCollision(this, b, null);
} else{
// if the ball hasn't collided with anything process its movement based on speed
// this assumes a 1000 x 1000 window for keeping objects inside it
if(this.ballX < 1000 - this.ballWidth && this.ballY < 1000 - this.ballHeight){
this.ballX += this.xSpeed;
this.ballY += this.ySpeed;
}else {
processCollision(this, null, new Wall());
}
}
}
try
{
Thread.sleep(1);
}
catch(Exception e)
{
}
}
public void processCollision(Ball b1, Ball b2, Wall w){
// if ball hasn't collided with a wall, process a ball - ball collision
if(w == null){
// apply physics mechanics according the complexity desired for ball collisions
b1.xSpeed -= b2.xSpeed;
b1.ySpeed -= b2.ySpeed;
// ball 2 would end up slowing down
b2.xSpeed -= b1.xSpeed;
b2.ySpeed -= b1.ySpeed;
}
// if ball hasn't collided with a ball, process a ball - wall collision
if(b2 == null){
// apply physics mechanics for hitting a wall
// e.g as below: just send ball in opposite direction
b1.xSpeed = b1.xSpeed * -1;
b1.ySpeed = b1.ySpeed * -1;
}
// either way, process ball's new position based on its new speed
b1.ballX += b1.xSpeed;
b1.ballY += b1.ySpeed;
b2.ballX += b2.xSpeed;
b2.ballY += b2.ySpeed;
}

Processing / How to make selectable object, that moves where i click

that really sucks ... i know how to make classes, objects, interfaces, loops etc . But everytime i try to make a unit or more than one, that is moving (when i select it) to the point where i click i get errors, errors and errors .... Why the hell theres nowhere a tutorial for that ?
My new class looks so atm :
class Unit {
int X;
int Y;
int Breite;
int Laenge;
int ID;
boolean ausgewaelht = false;
Unit() {
}
Unit(int x, int y, int breite, int laenge) {
}
void create(UnitContent function) {
function.form();
}
void move(float geschwindigkeit) {
if(isTriggerd(X,Y,Breite,Laenge) == true){
X = X+(int)geschwindigkeit;
if(X > width) {
X = 0;
}
}
}
void setXandY(int x , int y) {
X = x;
Y = y;
}
void setBreiteandLaenge(int breite, int laenge) {
Breite = breite;
Laenge = laenge;
}
void setID(int id) {
ID = id;
}
int getX() {
return X;
}
int getY() {
return Y;
}
int getBreite() {
return Breite;
}
int getLaenge() {
return Laenge;
}
int getID() {
return ID;
}
boolean isTriggerd(int x, int y, int breite, int laenge) {
if(mouseX > x && mouseX < x+breite && mouseY > y && mouseY < y+laenge ) {
return true;
}
else {
return false;
}
}
}
IS there something i forgot ?
And how do i display 10 or 50 units of them?
sorry for my bad english :) and thx for your help
Some friendly advice: your tone comes off sounding a bit demanding, and your description is very vague. You'll have much better luck if you try to make it easy for other people to help you.
Tell us exactly what errors you're getting.
Post an MCVE with enough code so we can run it, but not any code that isn't directly related to your problem.
Try breaking your problem down into small steps, and only ask one specific question at a time.
Check out the question checklist and make sure you've done everything on the list.
Why the hell theres nowhere a tutorial for that ?
Keep in mind that the people answering questions on Stack Overflow are doing so for free, in their spare time. The people developing Processing are doing so for free, in their spare time. Even so, there are a ton of tutorials on your problems. Have you tried searching on google?
Here is a tutorial that does exactly what you're looking for. These examples come with the Processing editor (go to File -> Examples). The reference is another great resource that you should check out.
All of that being said, I'll walk you through solving this problem, and hopefully how to solve other problems in the future.
Step 0: Break your problem down into smaller steps. This is the golden rule of programming. Whenever you're stuck, go back to this step. This step fuels the rest of the steps, and it should be the first, second, and third thing you do whenever you're stuck.
Step 1: Can you draw a single object? Don't worry about interaction or multiple objects or anything else, just draw a single object. Get that code working first.
Here's code that draws a single circle:
void setup(){
size(500, 500);
ellipseMode(CENTER);
}
void draw(){
background(0);
ellipse(100, 200, 50, 50);
}
Step 2: Can you encapsulate the information needed to draw the object in a class? Again, only worry about the next small step- don't worry about multiple shapes yet. Just get a class working for a single object. Here is how we might encapsulate the data for our circle:
Circle circle;
void setup() {
size(500, 500);
ellipseMode(CENTER);
circle = new Circle(100, 200, 50);
}
void draw() {
background(0);
circle.draw();
}
class Circle {
float x;
float y;
float r;
public Circle(float x, float y, float r) {
this.x = x;
this.y = y;
this.r = r;
}
void draw() {
ellipse(x, y, r, r);
}
}
If you have trouble on this step, then you can post something like this small example with a more specific question, and it'll be much easier to help you than if you post a section of your entire sketch without any specific errors.
Step 3: Can you add some simple user interaction logic to your circle class? Don't worry about clicking yet, just try to change the color of the circle when you move your mouse over it.
Circle circle;
void setup() {
size(500, 500);
ellipseMode(RADIUS);
circle = new Circle(100, 200, 50);
}
void draw() {
background(0);
circle.draw();
}
class Circle {
float x;
float y;
float r;
public Circle(float x, float y, float r) {
this.x = x;
this.y = y;
this.r = r;
}
void draw() {
if(dist(mouseX, mouseY, x, y) < r){
//mouse is inside circle
fill(0, 255, 0);
}
else{
//mouse is outside circle
fill(0, 0, 255);
}
ellipse(x, y, r, r);
}
}
By breaking your bigger problem down into these smaller steps, it becomes much easier to debug your code than if you try to write your entire sketch at one time.
Step 4: Can you improve your interaction code to detect a click? Can you move the circle when a drag is detected?
You should probably break those steps down even further, but for the sake keeping this post short(er), I've combined them into one:
Circle circle;
void setup() {
size(500, 500);
ellipseMode(RADIUS);
circle = new Circle(100, 200, 50);
}
void draw() {
background(0);
circle.draw();
}
class Circle {
float x;
float y;
float r;
public Circle(float x, float y, float r) {
this.x = x;
this.y = y;
this.r = r;
}
void draw() {
if(dist(mouseX, mouseY, x, y) < r){
//mouse is inside circle
if(mousePressed){
//mouse is being dragged
fill(255, 0, 0);
//move the circle to the mouse position
x = mouseX;
y = mouseY;
}
else{
//mouse is not clicked
fill(0, 255, 0);
}
}
else{
//mouse is outside circle
fill(0, 0, 255);
}
ellipse(x, y, r, r);
}
}
Step 5: Can you make it work for multiple objects? If you've done a good job of breaking your problem down into small steps and encapsulating your logic into a class, then this step becomes pretty easy.
ArrayList<Circle> circles = new ArrayList<Circle>();
void setup() {
size(500, 500);
ellipseMode(RADIUS);
for (int i = 0; i < 10; i++) {
circles.add(new Circle(random(width), random(height), random(10, 50)));
}
}
void draw() {
background(0);
for (Circle circle : circles) {
circle.draw();
}
}
class Circle {
float x;
float y;
float r;
public Circle(float x, float y, float r) {
this.x = x;
this.y = y;
this.r = r;
}
void draw() {
if (dist(mouseX, mouseY, x, y) < r) {
//mouse is inside circle
if (mousePressed) {
//mouse is being dragged
fill(255, 0, 0);
//move the circle to the mouse position
x = mouseX;
y = mouseY;
} else {
//mouse is not clicked
fill(0, 255, 0);
}
} else {
//mouse is outside circle
fill(0, 0, 255);
}
ellipse(x, y, r, r);
}
}
To summarize, you need to break your problem down into smaller steps and take on those steps one at a time. If you get stuck on a specific step (or if you don't understand one of the steps in my answer) then you can post a small example MCVE like my examples above, and ask a specific question.
Happy coding!
It really doesn't look like you have any graphical code except for some coordinates. In order to display something in Java you have to use a library that supports it like Swing or JavaFX. Here's a SO question that will give you some idea of what the differences are. Happy coding!

Multiple classes in processing

I'm making a game where you're controlling a square, and objects will spawn in random places, which you have to pick up to get points, while also having to dodge big squares going from side to side. Right now I have 2 classes (one for enemies - big squares -, and one for the hero), I haven't done the point system yet with the spawning objects, but that's not what I'm trying to do now.
So my problem right now is that I don't really know how to make the person lose the game/a life when you touch the "enemies" with your hero. I would know how to do it without classes, but I'd like to know how to do it when they are in separate classes.
If someone could explain with code and comments how this would be done, it would help me out a lot :) (I read something about 'extends' for classes but I'm not sure if this is what I should use or not).
Here's a screenshot of what my game looks like at the moment, just to better illustrate it:
Here's the main code page:
Hero myHero = new Hero(400,480,5);
Enemies myEnemies = new Enemies(50,50,10);
Enemies myEnemies2 = new Enemies(50,350,15);
Enemies myEnemies3 = new Enemies(50,650,12);
void setup() {
size(900,800);
frameRate(30);
smooth();
}
void draw() {
background(0);
myHero.keyPressed();
myEnemies.enemyDisplay();
myEnemies.enemyMove();
myEnemies2.enemyDisplay();
myEnemies2.enemyMove();
myEnemies3.enemyDisplay();
myEnemies3.enemyMove();
}
Class 1:
class Enemies {
float xpos, ypos, speed;
Enemies(float x, float y, float s) {
xpos = x;
ypos = y;
speed = s;
}
void enemyDisplay() {
rect(xpos, ypos, 100, 100);
}
void enemyMove() {
xpos += speed;
if((xpos > width - 100) || (xpos < 0)) {
speed *= -1;
}
}
}
Class 2:
class Hero {
float xpos_, ypos_, speed_;
Hero(float x, float y, float s) {
xpos_ = x;
ypos_ = y;
speed_ = s;
}
void keyPressed() {
if (key == CODED) {
if (keyCode == UP) {
ypos_ -= speed_;
}
if (keyCode == DOWN) {
ypos_ += speed_;
}
if (keyCode == LEFT) {
xpos_ -= speed_;
}
if (keyCode == RIGHT) {
xpos_ += speed_;
}
}
rect(xpos_,ypos_,30,30);
}
}
I believe the question you are asking involves basic collision detection and object interactions.
I would first make the Enemies a List and create it / add elements during the setup() call:
List<Enemies> enemies = new List<Enemies>();
enemies.add(new Enemies(50,50,10));
This allows you to store all of your Enemies under one object. So your draw() method would look something like:
void draw(){
background(0);
myHero.keyPressed();
for(Enemies enemy : enemies)
{
enemy.enemyDisplay();
enemy.enemyMove();
if (hero.isCollidingWith(enemy)) // collision method defined in the hero object, but you could define it in the Enemies class as well, it doesn't really matter
{
hero.removeHealth(); // method defined in hero that removes health
}
}
}
This method would be in one of your classes:
public boolean isColliding(Enemies enemy)
{
// check the x and y coordinates of each object
}
I hope this helps to point you in the right direction.
you need to figure out collision detection and when your objects collide with each other, something basic like:
class Enemy
{
//...
public boolean isColliding(Hero hero)
{
//figure out the distance between two objects, if its less than their size, they are colliding..
//...
}
//...
}
then you need a part of your Game Loop that checks if anything is colliding with your hero, pickups, walls, etc...
It seems the first part you need help with is collision detection. The short answer I would give that will almost undoubtedly lead you to more questions is to look at the Area class (specifically Area.intersect). You might also want to look at the classes I've put together for displaying & managing areas in this project here
There are several problems here that touch on both application design as well as conventions. These should be addressed first before trying to tackle the collision detection problem.
The Enemies class only represents a single enemy, so the name of the class should reflect that. Additionally, prefixing the method names with "enemy" is redundant and can be removed. Other changes have been commented in the revised class below.
public class Enemy {
// Instead of hard-coding in the width and height of an enemy, allow the
// instantiating code to specify the enemy's size. This will allow you
// to have different size enemies and prevents you from having "magic numbers"
// in your code.
private float xpos, ypos, width, height, speed;
public Enemy(float x, float y, float s, float w, float h) {
xpos = x;
ypos = y;
width = w;
height = h;
speed = s;
}
/* These getters will be used for collision detection later */
public float getX() {
return xpos;
}
public float getY() {
return ypos;
}
public float getWidth() {
return width;
}
public float getHeight() {
return height;
}
// I've changed `display` to `draw` to be consistent with the method name in
// your main `draw` method.
public void draw() {
rect(xpos, ypos, width, height);
}
// This method now accepts a screenWidth parameter so that the enemy can know
// when they've collided with the left or right wall of the screen without
// having to rely on an global variable.
public void move(int screenWidth) {
xpos += speed;
if ((xpos > screenWidth - width) || (xpos < 0)) {
speed *= -1;
}
}
}
I mention the "magic numbers" in one of the comments above. See this wikipedia article for more on that.
The Hero class contains property names that have an underscore postfix. This ranges from unconventional to inconsistent with respect to all of your other property names in your other classes. The original keyPressed() method mixes the logic for both drawing and moving. These two things have been separated and the methods named like those of the Enemy class for consistency.
public class Hero {
private float xpos, ypos, width, height, speed;
public Hero(float x, float y, float s, float w, float h) {
xpos = x;
ypos = y;
width = w;
height = h;
speed = s;
}
// Change this method name to draw for consistency with the Enemy class
public void draw() {
// Key press functionality has been moved to the `move` method for consistency
// with the Enemy class.
rect(xpos, ypos, WIDTH, HEIGHT);
}
// This method uses the variables key, keyCoded, UP, DOWN, LEFT, and RIGHT. You
// did not include any import statements with your code, so they may be coming
// from there; however, if they are globals, you should pass them to this method
// as arguments whenever you call it.
public void move() {
// If this condition isn't satisfied, return immediately. This prevents
// unnecessary nesting and work below.
if (key != CODED) {
return;
}
if (keyCode == UP) {
ypos -= speed;
}
// Use `else if` here and below to prevent multiple unnecessary
// comparisons of keyCode.
else if (keyCode == DOWN) {
ypos += speed;
}
else if (keyCode == LEFT) {
xpos -= speed;
}
else if (keyCode == RIGHT) {
xpos += speed;
}
}
public boolean isColliding(Enemy enemy) {
// Collision detection is easy since all of your game entities (the hero and
// the enemies) are all rectangles and axis-aligned (not rotated). You can
// use a method known as "bounding box intersection."
return (Math.abs(enemy.getX() - xpos) * 2 < (enemy.getWidth() + width))
&& (Math.abs(enemy.getY() - ypos) * 2 < (enemy.getHeight() + height));
}
}
For more on bounding box intersection, see this gamedev stackexchange question.
Now that your classes are in order, its time to address your main code. We'll need to update the method names and, as #James T suggested, you should make a list of enemies instead of creating a new independent object for each enemy. This will make it easier for you to add or remove enemies in the future and to be able to process all enemies with one block of code without repeating yourself.
// Use constants to remove magic numbers.
private static final int SCREEN_WIDTH = 900;
private static final int SCREEN_HEIGHT = 800;
private Hero myHero = new Hero(400, 480, 30, 30, 5);
private List<Enemy> enemies = new ArrayList<Enemy>();
void setup() {
size(SCREEN_WIDTH, SCREEN_HEIGHT);
frameRate(30);
smooth();
enemies.add(new Enemy(50, 50, 100, 100, 10));
enemies.add(new Enemy(50, 350, 100, 100, 15));
enemies.add(new Enemy(50, 650, 100, 100, 12));
}
void draw() {
hasCollision = false;
background(0);
// I've changed the order of draw->move to move->draw. If you draw first, then
// move, then detect collisions, it will appear to your user that your hero has
// not yet collided with an enemy even though you act as they have (e.g.: they
// will not see the collision until the next time you draw the scene).
myHero.move();
myHero.draw();
for (Enemy enemy : enemies) {
enemy.move();
enemy.draw(SCREEN_WIDTH);
if (!hasCollision && myHero.isColliding(enemy)) {
hasCollision = true;
}
}
if (hasCollision) {
// Handle enemy collision here
}
}
You'll notice that I've also added accessibility modifiers to everything. While it is technically valid to exclude them and use the defaults, it makes your code more readable to include them because it is more obvious. When you're first starting out, the more obvious the better.
Alright got it to work thanks to all you helpful wonderful people!
I did this:
public boolean isColliding(Enemies h){
float distance = dist(x,y,h.x,h.y);
if(distance<100){
return true;
}else{
return false;
}
}
and in my draw(){ I have
if(myHero.isColliding(myEnemies)){
println("You lost!");
}
I had a very similar 'fix' earlier, but the reason I got an error was because I had Hero h instead of Enemies h in the 'if' function, so it was just a very dumb error that I overlooked :P

Slick2D Rectangle Collision Detection

I'm having an issue showing that one rectangle has collided with another. So my question is, how can I get the intersect method to check for collision? Or are there any other ways to handle collision in this situation?
I'm creating a turn-based combat game (similar to Final Fantasy or Legend of Dragoon) where the player's character is on the right side of the screen and the enemy is on the left side. The player and enemy each take turns attacking. So when the player attacks, the sprite animation moves across the screen from right to left until it stops in front of the enemy, attacks, and returns to it's starting coordinates. Both the player and enemy have a rectangle drawn around them to represent the bounds of each character.
When the player moves forward, he passes through the Enemy's rectangle and stops within it. At this point there should be output to the console saying "INTERSECT!" to show that there was a collision between the two rectangles, but unfortunately there isn't.
Please note that I have omitted the unnecessary pieces of code within my classes and tried to provide the code that pertains to my problem.
This is my entry point, GameClass:
public class GameClass extends BasicGame{
//other variable declarations
public void init(GameContainer container) throws SlickException {
player = new Player();
enemy = new Enemy();
skeleton = new Skeleton();
enemy = skeleton;
playX = player.getStartX(); //700
playY = player.getStartY(); //140
playW = player.rect.getWidth(); //40
playH = player.rect.getHeight(); //70
enemyX = enemy.getStartX(); //100
enemyY = enemy.getStartY(); //140
enemyWidth = enemy.getWidth(); //50
enemyHeight = enemy.getHeight(); //55
SpriteSheet sheet = new SpriteSheet("data/homeranim.png", 36, 65);
anim = new Animation();
for (int i=0;i<8;i++) {
anim.addFrame(sheet.getSprite(i,0), 150);
}
}
public void render(GameContainer container, Graphics g)
throws SlickException {
anim.draw(playX,playY); // draws player animation
skeletonAnim.draw(enemyX, enemyY); // draws enemy
g.draw(player.rect); //draws player bounds
g.draw(enemy.rect); //draws enemy bounds
}
public void update(GameContainer container, int delta)
throws SlickException {
playerUpdate(delta);
if (player.rect.intersects(enemy.rect)) {
System.out.println("INTERSECT!");
System.out.println("Player minX: " + player.rect.getMinX());
System.out.println("Player maxX: " + player.rect.getMaxX());
System.out.println("Enemy minX: " + enemy.rect.getMinX());
System.out.println("Enemy maxX: " + enemy.rect.getMaxX());
}
}
public void playerUpdate(int delta) {
if (playerForward == true){
playX -= delta * 0.4f;
if (playX <= 140) {
playX = 140;
playerForward = false;
playerBackward = true;}
}
if (playerBackward == true) {
playX += delta * 0.4f;
if (playX >= 700) {
playX = 700;
playerBackward = false;
delay = 1250;
}
public void keyReleased(int key, char c) {
if (key == Input.KEY_ENTER){
playerForward = true;}
}
}
This is a glimpse at my Player class:
public class Player {
private int startX = 700;
private int startY = 140;
public Shape rect = new Rectangle(startX, startY, 40, 70);
//plus getters and setters
}
And my entire Enemy class:
public class Enemy {
private int startX, startY, width, height;
public Shape rect = new Rectangle(startX, startY, width, height);
// plus getters and setters
}
My Skeleton class extends Enemy:
public class Skeleton extends Enemy {
public Skeleton() {
// TODO Auto-generated constructor stub
setMaxHealth(120);
setStartX(100);
setStartY(140);
setWidth(50);
setHeight(55);
}
}
Note: Since I've switched g.drawRect() to g.draw(), enemy rectangle isn't being drawn.
Rect bounds at starting point: http://i.imgur.com/QDDk858.png
Rect bound where collision should be: http://i.imgur.com/pOANfvN.png
I hope I've provided enough code to show you what my problem is. I've rummaged through the internet for hours with no luck. If there is any other code I need to provide, please do not hesitate to ask. Thank you very much for your help and support!
You are not updating the hitbox positions themselves.
You are drawing this:
g.drawRect(playX, playY, playW, playH); //draws player bounds
g.drawRect(enemyX, enemyY, enemyW, enemyH); //draws enemy bounds
But this isn't the actual hitbox, it's just the position of the player/enemy and the rectangles drawn here will be on the correct position while the hitboxes themselves aren't.
I suggest you do the following:
public void update(GameContainer container, int delta)
{
playerUpdate(delta);
player.rect.setLocation(playX, playY);
enemy.rect.setLocation(enemyX, enemyY); // update the hitboxes to the new positions
if (player.rect.intersects(enemy.rect))
{
System.out.println("INTERSECT!");
}
}
public void playerUpdate(int delta)
{
if (playerForward == true)
{
playX -= delta * 0.4f;
if (playX <= 140)
{
playX = 140;
playerForward = false;
playerBackward = true;
}
}
if (playerBackward == true)
{
playX += delta * 0.4f;
if (playX >= 700)
{
playX = 700;
playerBackward = false;
delay = 1250;
}
}
}
public void keyReleased(int key, char c)
{
if (key == Input.KEY_ENTER)
{
playerForward = true;
}
}
Furthermore, as you seem to be new to game development in Java, some tips for you:
Format your code properly
Always place full {...} after if, else, switch, while, for, etc.; proper line indentation, .
Think OO (Object-Oriented)
This one is pretty important. Your enemy and player class should both extend some kind of entity class because they both will pretty much want to obtain similar behavior (avoid code duplication!). Sum up similar behavior to a super class, simplify the behavior to be controlled with a few adjustable parameters and so on.
For example, you store the positions of your enemy and player as a static integer in your main class. This is not OO. Move the positions to the entity class where you can implement it in whatever manner you wish.
Don't just throw an exception for no reason
Your update(...) method throws a SlickException even though it's never needed.
Be careful about encapsulation
This is something a lot of beginners do: Just grab some parameters, put them in a class as private (or maybe even public) and generate getters- and setters for them. This is not encapsulation. This is almost as bad as making them public in the first place.
But why don't we just make everything public?
We don't want anyone (or even ourselves) to rely on some parameters that just happen to be there because of some very specific implementation of something we might want to change later. Don't just put all possible values out there to be changed, the sense of encapsulation is to be independent from what kind of implementation we end up using and to protect the usability of our code by guarding what can be set/changed.
Performance does matter
This is one of the aspects you should watch out for, for any kind of software, but you can often most drastically see the consequences in games. Performance is important! And by that, I don't mean that you have to watch out for every single detail, but just keep an overview in mind on how to improve and fasten up your code, especially with frequently called methods such as update(..) and render(..) in Slick2D.
Update
As a solution to another problem discussed in the comments:
public class Enemy {
private int startX, startY, width, height;
public Shape rect = new Rectangle(startX, startY, width, height);
// plus getters and setters
}
width and height can only be 0 as they are never assigned an integers have the value 0 per default, so the enemy rectangle hitbox does have 0 width and will never trigger.
Try something like:
public class Enemy {
private int startX, startY, width = 50, height = 70;
public Shape rect = new Rectangle(startX, startY, width, height);
// plus getters and setters
}
This should work, but you should probably move all these attributes to the enemy class and put them in the constructor.

Coding a game of Pool in Java - how can I define the balls and move them (via Graphics g)?

My plan is to design a simple game of Pool in Java.
OOP makes the most sense here for the balls. All the balls have the same functionality, so because of that it would be a good idea to make a Ball class that would handle the relative position of the ball and other variables such as when it goes in a hole it removes itself and increments your score. So when it hits a hole Ball.dispose (); would fit nicely.
My issue is that I do not know how to manipulate the ball and dispose of it. Also inorder to move it I rely on Thread.sleep instead of java.swing.timer because there is no available Action Performed method I can rely on.
How can I move the ball more easily and get rid of it when needed?
The green thing covering the ball is my way of erasing the last position of the ball by drawing a green oval over it.
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
public class Main extends JFrame{
Ball redball = new Ball (285, 600, 20, 20, Color.RED);
//variables to control redball
private int rX = redball.getX();
private int rY = redball.getY();
private final int rWidth = redball.getWidth();
private final int rHeight = redball.getHeight();
int Force = 30;
int Bearing = 20; // True Bearing
public Main (){
setSize(600, 800);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Pool");
}
public void paint(Graphics g){
super.paint(g);
// draw the table
g.setColor (Color.GREEN);
g.fillRect(100, 100, 400, 600);
g.setColor (Color.BLACK);
g.drawRect(99, 99, 401, 601);
//draw start ball
g.setColor(redball.getColor());
g.fillOval(rX, rY, rWidth, rHeight);
if (Force == 30){
for (int i = Force; i > 0;i--){
try {
Thread.sleep(100);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
Force--;
if (rY > 98 + rWidth) {
rY = rY - i;
rX = rX + (Bearing/5);
}
g.fillOval(rX, rY, rWidth, rHeight);
g.setColor(Color.GREEN);
repaint ();
g.fillOval(rX - (Bearing/5), rY + i, rWidth, rHeight); // repaint last ball
g.setColor(Color.RED);
repaint ();
}
}
// Ball.dispose (redball);
}
public static void main(String[] args) {
new Main();
}
Here is the class for the ball
public class Ball {
private int x;
private int y;
private int width;
private int height;
private Color color;
public Ball (int x, int y, int width, int height, Color color)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
}
public void setX (int x){
this.x = x;
}
public int getX (){
return this.x;
}
public void setY (int x){
this.y = y;
}
public int getY (){
return this.y;
}
public void setWidth (int width){
this.width = width;
}
public int getWidth (){
return this.width;
}
public void setHeight (int height){
this.height = height;
}
public int getHeight (){
return this.height;
}
public void setColor (Color color){
this.color = color;
}
public Color getColor (){
return this.color;
}
public static void dispose(Ball ball) {
ball = null; // if I call this method nothing happens
}
}
What I would do is maintain a List<Ball> field of all active balls. Then each iteration, iterate through that list and update and paint the Balls. When a Ball goes away, it's simply a matter of removing it from the list.
A consideration is: Who determines when its time to dispose of a ball? If something outside the Ball does, you have a few options, among others:
As I mentioned above, you could simply remove the Ball from the list.
You could set a "dead" flag in the Ball elsewhere, then on each iteration remove all Balls from the list whose "dead" flag has been set.
If the Ball itself determines when it is time to go away, you have a few options, among others, there as well:
Perhaps a method boolean Ball.think(), that updates the state of the ball and returns true if the Ball is still good, or false if its dead. Then when you iterate through your list of balls, you call think() on all of them to update, and remove ones from the List that returned false.
Related to option 2 above, if a Ball has a think method or something similar, the ball can set its own "dead" flag (or something outside the Ball can set it), then the main loop can remove dead balls from the list.
If you want to keep the Ball instance around and just not draw it, you have a few options there too:
Simply skip processing of Balls marked as "dead" instead of removing them.
Move "dead" balls to a different dead Ball list.
Personally, I like the boolean think() method, because it easy allows you to specify a base interface for objects in the scene. You can also have objects paint themselves in that case. E.g.:
interface Entity {
public boolean think ();
public void paint (Graphics g);
}
class Ball implements Entity {
#Override public boolean think () {
// return true if alive, false if dead
}
#Override public void paint (Graphics g) {
// draw this ball
}
}
// then in your main update loop:
List<Entity> entities = ...;
Iterator<Entity> eit = entities.iterator();
while (eit.hasNext())
if (!eit.next().think())
eit.remove();
// and in paint:
for (Entity e:entities)
e.paint(graphics);
If you want to take the option I mentioned above of just skipping "dead" balls instead of removing them, something like this would be more appropriate (leaving out Ball for brevity), where isActive() returns true if the ball is active or false if it is temporarily "dead":
interface Entity {
public boolean isActive ();
public void think (); // think returns nothing
public void paint (Graphics g);
}
// then in your main update loop:
List<Entity> entities = ...;
for (Entity e:entities)
if (e.isActive())
e.think();
// it is the responsibility of something outside the ball to restore it to an
// active state, since think() isn't called if !isActive(). alternatively, you
// could always call think(), and just don't paint inactive balls.
// and in paint:
for (Entity e:entities)
if (e.isActive())
e.paint(graphics);
Still, you don't have to do it that way, there are plenty of arguments for all of the options listed above, and more. In your application, for example, there's not much need for an Entity interface if you know you are only dealing with Balls; and think() might not be the most convenient way to go if all of your physics logic is happening somewhere else (although of course the code could be written to place the logic in Ball).
As you can see there are many ways to skin a cat, but I hope something here helps.
Here are some suggestions.
Create a Rack class that contains all of the balls for your game.
Move the draw code for a ball into your Ball class. I realize that this suggestion is not pure MVC, but games are a lot easier to code when objects draw themselves.
Don't try to repaint part of the screen. It's a lot easier, and pretty fast, to just redraw the entire screen.
Don't dispose any Ball instances. Move it to some negative position that your draw code recognizes and doesn't draw.
When you're coding an action game, your main loop should look something like this (psudeocode).
while (running) {
calculateRackPosition();
drawRack();
Thread.sleep(100L);
}
You incrementally move the balls, then redraw the screen. This is how you code any animation. This code would run while the balls are moving.
You would write other code for when the person is aiming his shot.

Categories

Resources