Thread.sleep() and GUI - java

i just searched on the forum but I couldn't find anything that helps me.. My problem is the following : I was trying to create a little game in which you have to walk right in your friend's back in order to win, the game ends when one of them achieves this..
Here's a simple code I made to explain my problem
I have 3 classes in my application (which belong in the package code) :
Main
Game
Position
I have 9 .png in my application (which belong in the package img) :
0.png
j1_0.png
j1_1.png
j1_2.png
j1_3.png
j2_0.png
j2_1.png
j2_2.png
j2_3.png
Both packages are at the src root
First class :
package code;
public class Main{
public static Game game;
public static void main(String[] args){
game = new Game(8, 8);
}
}
Seconds class :
package code;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class Game extends JFrame{
private Position j1, j2;
private JPanel panel;
private JLabel[][] grid;
private int largeur, hauteur;
public Game(int hauteur, int largeur){ // >= 2
super("Rattrape l'autre");
this.largeur = largeur;
this.hauteur = hauteur;
this.panel = new JPanel(new GridBagLayout());
this.add(this.panel);
this.grid = new JLabel[largeur][hauteur];
int x1 = (int) (Math.random() * largeur), y1 = (int) (Math.random() * hauteur), x2, y2;
do{
x2 = (int) (Math.random() * largeur);
y2 = (int) (Math.random() * hauteur);
}while(x2 == x1 && y2 == y1);
this.j1 = new Position(x1, y1, (int) (Math.random() * 4));
this.j2 = new Position(x2, y2, (int) (Math.random() * 4));
updatePanel();
this.setResizable(false);
this.pack();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setVisible(true);
this.addKeyListener(new KeyListener(){
#Override
public void keyPressed(KeyEvent e){
boolean over = false;
if(e.getKeyCode() == KeyEvent.VK_Z){
if(j1.getY() != 0 && !(j1.getY() == j2.getY() + 1 && j1.getX() == j2.getX())){
j1.goesUp();
}else if(j2.getDirection() == 0 && j1.getY() == j2.getY() + 1 && j1.getX() == j2.getX()){
over = true;
}
j1.turnUp();
}else if(e.getKeyCode() == KeyEvent.VK_D){
if(j1.getX() != largeur - 1 && !(j1.getX() == j2.getX() - 1 && j1.getY() == j2.getY())){
j1.goesRight();
}else if(j2.getDirection() == 1 && j1.getX() == j2.getX() - 1 && j1.getY() == j2.getY()){
over = true;
}
j1.turnRight();
}else if(e.getKeyCode() == KeyEvent.VK_S){
if(j1.getY() != hauteur - 1 && !(j1.getY() == j2.getY() - 1 && j1.getX() == j2.getX())){
j1.goesDown();
}else if(j2.getDirection() == 2 && j1.getY() == j2.getY() - 1 && j1.getX() == j2.getX()){
over = true;
}
j1.turnDown();
}else if(e.getKeyCode() == KeyEvent.VK_Q){
if(j1.getX() != 0 && !(j1.getX() == j2.getX() + 1 && j1.getY() == j2.getY())){
j1.goesLeft();
}else if(j2.getDirection() == 3 && j1.getX() == j2.getX() + 1 && j1.getY() == j2.getY()){
over = true;
}
j1.turnLeft();
}
if(e.getKeyCode() == KeyEvent.VK_UP){
if(j2.getY() != 0 && !(j2.getY() == j1.getY() + 1 && j2.getX() == j1.getX())){
j2.goesUp();
}else if(j1.getDirection() == 0 && j2.getY() == j1.getY() + 1 && j2.getX() == j1.getX()){
over = true;
}
j2.turnUp();
}else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
if(j2.getX() != largeur - 1 && !(j2.getX() == j1.getX() - 1 && j2.getY() == j1.getY())){
j2.goesRight();
}else if(j1.getDirection() == 1 && j2.getX() == j1.getX() - 1 && j2.getY() == j1.getY()){
over = true;
}
j2.turnRight();
}else if(e.getKeyCode() == KeyEvent.VK_DOWN){
if(j2.getY() != hauteur - 1 && !(j2.getY() == j1.getY() - 1 && j2.getX() == j1.getX())){
j2.goesDown();
}else if(j1.getDirection() == 2 && j2.getY() == j1.getY() - 1 && j2.getX() == j1.getX()){
over = true;
}
j2.turnDown();
}else if(e.getKeyCode() == KeyEvent.VK_LEFT){
if(j2.getX() != 0 && !(j2.getX() == j1.getX() + 1 && j2.getY() == j1.getY())){
j2.goesLeft();
}else if(j1.getDirection() == 3 && j2.getX() == j1.getX() + 1 && j2.getY() == j1.getY()){
over = true;
}
j2.turnLeft();
}
updatePanel();
if(over){
end();
}
}
#Override
public void keyReleased(KeyEvent e){}
#Override
public void keyTyped(KeyEvent e){}
});
}
public void updatePanel(){
GridBagConstraints c = new GridBagConstraints();
this.panel.removeAll();
for(int x = 0; x < largeur; x++){
for(int y = 0; y < hauteur; y++){
if(x == j1.getX() && y == j1.getY()){
this.grid[x][y] = new JLabel(new ImageIcon(Main.class.getResource("/img/j1_" + j1.getDirection() + ".png")));
}else if(x == j2.getX() && y == j2.getY()){
this.grid[x][y] = new JLabel(new ImageIcon(Main.class.getResource("/img/j2_" + j2.getDirection() + ".png")));
}else{
this.grid[x][y] = new JLabel(new ImageIcon(Main.class.getResource("/img/0.png")));
}
c.gridx = x;
c.gridy = y;
this.panel.add(this.grid[x][y], c);
}
}
this.panel.revalidate();
}
public void end(){
try{
Thread.sleep(1000);
}catch(InterruptedException e){}
Main.game.dispose();
}
}
Third class :
package code;
public class Position{
private int x, y, direction;
public Position(int x, int y, int direction){
this.x = x;
this.y = y;
this.direction = direction;
}
public int getX(){
return this.x;
}
public int getY(){
return this.y;
}
public int getDirection(){
return this.direction;
}
public void goesUp(){
this.y--;
}
public void goesRight(){
this.x++;
}
public void goesDown(){
this.y++;
}
public void goesLeft(){
this.x--;
}
public void turnUp(){
this.direction = 0;
}
public void turnRight(){
this.direction = 1;
}
public void turnDown(){
this.direction = 2;
}
public void turnLeft(){
this.direction = 3;
}
}
Finally, my problem is this one :
I wanted that, for example, when the Player 1 looks left and he's just on top of the Player 2, while the Player 2 looks down, if the player 1 moves down, it should wins the game, but AFTER displaying the Player 1 looking down.
I tried a lot of input o test, and it seems to work because when over is set to true, then the program goes in updatePanel() and then it launches end() which should sleep for 1 second and then dispose the frame.. but it doesn't, it does launch updatePanel() at the end, it update the value of j1 (as the previous algorithm, i mean the one that assignes values in function of the keyboard inputs, made him look down) but it doesn't display the new grid so, i'm lost :p
Thanks in advice I hope you got the problem, plus the algorithm is easy and not that long so it shouldn't be hard for you guys to understand it :)

should sleep for 1 second and then dispose the frame..
You can't use Thread.sleep() on the Event Dispatch Thread(EDT). This will cause the GUI to sleep which means it will not get repainted.
Instead you need to use a separate Thread, probably a SwingWorker. A SwingWorker will allow you to use Thread.sleep() and then you can publish results when you are finished sleeping.
Read the section from the Swing tutorial on Concurrency for more information and examples.

Related

Adding KeyListener in Java

This a small game. Here I made 2 rectangles of same size. I want to move them whenever a person presses a key on keyboard. But I dont know how to add KeyListener. I had looked through previous answers here but I couldn't catch my mistake. I even searched the google but no clue. This is my code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
class PongGame extends JComponent implements ActionListener {
int ballX = 200;
int ballY = 340;
short ballX_Direction = 1;
short ballY_Direction = 1;
static int Direction1 = 300;
static int Direction2 = 300;
private static keyListener move;
public static void main(String[] args) {
JFrame frame = new JFrame("Pong Game");
PongGame game = new PongGame();
frame.add(game);
frame.pack();
frame.setSize(900,700);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setResizable(false);
Timer t = new Timer(2,game);
t.start();
}
public void paintComponent(Graphics g) {
g.setColor(new Color(0,242,237));
g.fillRect(0,0,900,700);
g.setColor(Color.black);int a = 60;
for(int i = 1;i<=5;i++) {
g.fillRect(444,0+a,12,65);
a = a+125;
}
g.setColor(Color.blue);
g.fillRect(100,Direction2,15,100);
g.fillRect(770,Direction1,15,100);
g.setColor(Color.red);
g.fillOval(ballX,ballY,20,20);
repaint();
}
public void actionPerformed(ActionEvent e) {
ballX = ballX + ballX_Direction;
ballY = ballY + ballY_Direction;
if(ballY >= 660) ballY_Direction = -1;
if(ballY <= 0) ballY_Direction = 1;
if(ballX >= 444-20 && ballY >= 60-20 && ballX <= 444-20 && ballY <= 185-20) {
ballX_Direction = -1;
}
if(ballX >= 444-20 && ballY >= 185-20 && ballX <= 444-20 && ballY <= 250-20) {
ballX_Direction = -1;
}
if(ballX >= 444-20 && ballY >= 250-20 && ballX <= 444-20 && ballY <= 375-20) {
ballX_Direction = -1;
}
if(ballX >= 444-20 && ballY >= 375-20 && ballX <= 444-20 && ballY <= 500-20) {
ballX_Direction = -1;
}
if(ballX >= 444-20 && ballY >= 500-20 && ballX <= 444-20 && ballY <= 625-20) {
ballX_Direction = -1;
}
repaint();
}
}
class keyListener implements KeyListener {
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_UP)
{
PongGame.Direction1 = PongGame.Direction1 - 25
}
if(key == KeyEvent.VK_DOWN)
{
PongGame.Direction1 = PongGame.Direction1 - 25;
}
if(key == '1')
{
PongGame.Direction2 -= 25;
}
if(key == '4')
{
PongGame.Direction2 += 25;
}
}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
}
JFrame has a method for that:
frame.addKeyListener(new keyListener());
It needs to be added to a GUI part, in particular a part that has focus, since that is the thing the OS tells about input.

how to fix the scoring issue in pong game

I am writing one of my first games in java and i need help on the scoring part of it. The score of each player is supposed to increase each time the ball touches the opposing side. on one side it works perfectly fine but on the other it doesn't work. Also, is it healthy/normal to have as many if statements as much as I do in the code?
P.S. I know my code is very messy but this is the first time I am creating something without a full tutorial explaining everything.
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Pong extends JPanel implements KeyListener{
int x = 90;
int y = 90;
int rectytop = 30;
int rectytop2 = 30;
int rectybottom = rectytop + 100;
int rectybottom2 = rectytop2 + 100;
int scoreplayer1 = 0;
int scoreplayer2 = 0;
int xedge2= 448;
int border = 30;
int scoreplayer1a = (int) scoreplayer1;
boolean balldown = true;
boolean ballright = true;
boolean playerborderup = false;
boolean playerborderdown = false;
boolean balltouch1 = false;
boolean balltouch2 = false;
boolean w = false;
boolean s = false;
boolean up = false;
boolean down = false;
boolean goalon1 = false;
boolean goalon2 = false;
private void moveball() {
if (balldown == true){
y = y + 2;
}
if (y >= getHeight()-border){
balldown = false;
}
if (balldown == false){
y = y - 2;
}
if (ballright == true){
x = x + 2;
}
if (x == getWidth()-border){
ballright = false;
}
if (ballright == false){
x = x - 2;
}
if (y == 0){
balldown = true;
}
if (x == 0){
ballright = true;
}
if (balltouch1 == false){
if (x == 76){
if(y < rectybottom && y > rectytop){
ballright = true;
}
}
}
if (balltouch2 == false){
if (x == 390 && y < rectybottom2 && y > rectytop2){
ballright = false;
}
}
}
#Override
public void paint(Graphics g){
super.paint(g);
//drawing ball
g.fillOval(x, y, 30, 30);
g.fillRect(48 , rectytop, 30, 100);
g.fillRect(420, rectytop2, 30, 100);
g.setFont(new Font("Arial", Font.PLAIN, 100));
g.drawString(Integer.toString(scoreplayer1a), 175, 100);
g.drawString(Integer.toString(scoreplayer2), 300, 100);
}
public Timer timer = new Timer(30, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
if (w == true){
if (rectytop == 0){
playerborderup = true;
}
if (rectytop != 0){
playerborderup = false;
}
if (playerborderup == true){
rectytop = rectytop + 0;
rectybottom = rectytop + 100;
repaint();
}
if (playerborderup == false){
rectytop = rectytop - 5;
rectybottom = rectytop + 100;
repaint();
}
}
if (s == true){
if (rectytop == 585){
playerborderdown = true;
}
if (rectytop != 585){
playerborderdown = false;
}
if (playerborderdown == true){
rectytop = rectytop - 0;
rectybottom = rectytop + 100;
repaint();
}
if (playerborderdown == false){
rectytop = rectytop + 5;
rectybottom = rectytop + 100;
repaint();
}
}
if (up == true){
if (rectytop2 == 0){
playerborderup = true;
}
if (rectytop2 != 0){
playerborderup = false;
}
if (playerborderup == true){
rectytop2 = rectytop2 + 0;
rectybottom2 = rectytop2 + 100;
repaint();
}
if (playerborderup == false){
rectytop2 = rectytop2 - 5;
rectybottom2 = rectytop2 + 100;
repaint();
}
}
if (down == true){
if (rectytop2 == 585){
playerborderdown = true;
}
if (rectytop2 != 585){
playerborderdown = false;
}
if (playerborderdown == true){
rectytop2 = rectytop2 - 0;
rectybottom2 = rectytop2 + 100;
repaint();
}
if (playerborderdown == false){
rectytop2 = rectytop2 + 5;
rectybottom2 = rectytop2 + 100;
repaint();
}
}
}
});
public void start(){
timer.start();
}
public static void main(String[] args) throws InterruptedException {
//making the window
JFrame f = new JFrame("Pong Game");
JPanel p = new JPanel();
Pong game = new Pong();
Font font = new Font("Courier", Font.BOLD, 30);
f.setVisible(true);
f.setSize(502, 502);//1024, 724
f.setResizable(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.addKeyListener(game);
f.add(game);
f.add(p);
game.start();
//game code
f.add(game);
while (true){
game.repaint();
game.moveball();
game.setscore();
Thread.sleep(10);
}
}
public void setscore(){
if (x == 0){
goalon1 = true;
}
if (x != 0){
goalon1 = false;
}
if (x == getWidth()-30){
goalon2 = true;
}
if (x != getWidth()-30){
goalon2 = false;
}
if (goalon1 == true){
scoreplayer2 ++;
}
if (goalon2 == true){
scoreplayer1 = scoreplayer1 + 1;
}
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
//player one
if (e.getKeyCode() == KeyEvent.VK_W){
w = true;
}
if (e.getKeyCode() == KeyEvent.VK_S){
s = true;
}
//player two
if (e.getKeyCode() == KeyEvent.VK_UP){
up = true;
}
if (e.getKeyCode() == KeyEvent.VK_DOWN){
down = true;
}
}
#Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_W){
w = false;
}
if (e.getKeyCode() == KeyEvent.VK_S){
s = false;
}
if (e.getKeyCode() == KeyEvent.VK_UP){
up = false;
}
if (e.getKeyCode() == KeyEvent.VK_DOWN){
down = false;
}
}
}
You do a lot of stuff differently for each player for no reason. It would be much more helpful if you narrowed down what part of the code the error was coming from or at least told us which player doesn't work and which does.
I'm not going to read all of the code you posted, but look at differences like this. The error might not be coming from setScore() alone. There is no way to tell without going through everything you posted.
if (goalon1 == true){
scoreplayer2 ++;
}
if (goalon2 == true){
scoreplayer1 = scoreplayer1 + 1;
}
Try to match the code for both players and I'm sure you'll find your mistake

ActionListener not working on some computers?

I was making a snake game, it works fine on my computer but doesn't work on any of the school computers. It compiles and I can run it but my keypressed events don't work, so i cannot control the snake because the keys don't work.
Snake Class
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.Timer;
public class Snake implements ActionListener, KeyListener
{
public static Snake snake;
public JFrame jframe;
public RenderPanel renderPanel;
public Timer timer = new Timer(20, this);
public ArrayList<Point> snakeParts = new ArrayList<Point>();
public static final int UP = 0, DOWN = 1, LEFT = 2, RIGHT = 3, SCALE = 10;
public int ticks = 0, direction = DOWN, score, tailLength = 10, time;
public Point head, mouse;
public Random random;
public boolean over = false, paused;
public Dimension dim;
public Snake()
{
dim = Toolkit.getDefaultToolkit().getScreenSize();
jframe = new JFrame("TechnoSnake");
jframe.setVisible(true);
jframe.setSize(805, 700);
jframe.setResizable(false);
jframe.setLocation(dim.width / 2 - jframe.getWidth() / 2, dim.height / 2 - jframe.getHeight() / 2);
jframe.add(renderPanel = new RenderPanel());
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.addKeyListener(this);
startGame();
}
public void startGame()
{
over = false;
paused = false;
time = 0;
score = 0;
tailLength = 1;
ticks = 0;
direction = DOWN;
head = new Point(0, -1);
random = new Random();
snakeParts.clear();
mouse = new Point(random.nextInt(79), random.nextInt(66));
timer.start();
}
public void actionPerformed(ActionEvent arg0)
{
renderPanel.repaint();
ticks++;
if (ticks % 2 == 0 && head != null && !over && !paused)
{
time++;
snakeParts.add(new Point(head.x, head.y));
if (direction == UP)
if (head.y - 1 >= 0 && noTailAt(head.x, head.y - 1))
head = new Point(head.x, head.y - 1);
else
over = true;
if (direction == DOWN)
if (head.y + 1 < 67 && noTailAt(head.x, head.y + 1))
head = new Point(head.x, head.y + 1);
else
over = true;
if (direction == LEFT)
if (head.x - 1 >= 0 && noTailAt(head.x - 1, head.y))
head = new Point(head.x - 1, head.y);
else
over = true;
if (direction == RIGHT)
if (head.x + 1 < 80 && noTailAt(head.x + 1, head.y))
head = new Point(head.x + 1, head.y);
else
over = true;
if (snakeParts.size() > tailLength)
snakeParts.remove(0);
if (mouse != null)
{
if (head.equals(mouse))
{
score += 10;
tailLength++;
mouse.setLocation(random.nextInt(79), random.nextInt(66));
}
}
}
}
public boolean noTailAt(int x, int y)
{
for (Point point : snakeParts)
{
if (point.equals(new Point(x, y)))
{
return false;
}
}
return true;
}
public static void main(String[] args)
{
snake = new Snake();
}
public void keyPressed(KeyEvent e)
{
int i = e.getKeyCode();
if ((i == KeyEvent.VK_A || i == KeyEvent.VK_LEFT) && direction != RIGHT)
direction = LEFT;
if ((i == KeyEvent.VK_D || i == KeyEvent.VK_RIGHT) && direction != LEFT)
direction = RIGHT;
if ((i == KeyEvent.VK_W || i == KeyEvent.VK_UP) && direction != DOWN)
direction = UP;
if ((i == KeyEvent.VK_S || i == KeyEvent.VK_DOWN) && direction != UP)
direction = DOWN;
if (i == KeyEvent.VK_SPACE)
if (over)
startGame();
else
paused = !paused;
}
public void keyReleased(KeyEvent e)
{
}
public void keyTyped(KeyEvent e)
{
}
}
RenderPanel Class
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import javax.swing.JPanel;
public class RenderPanel extends JPanel
{
//public static Color green = new Color(1666073);
public static Color brown = new Color(6697728);
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
//g.setColor(green);
g.setColor(Color.BLACK);
g.fillRect(0, 0, 800, 700);
Snake snake = Snake.snake;
g.setColor(Color.BLUE);
for (Point point : snake.snakeParts)
{
g.fillRect(point.x * Snake.SCALE, point.y * Snake.SCALE, Snake.SCALE, Snake.SCALE);
}
g.fillRect(snake.head.x * Snake.SCALE, snake.head.y * Snake.SCALE, Snake.SCALE, Snake.SCALE);
g.setColor(Color.RED);
g.fillRect(snake.mouse.x * Snake.SCALE, snake.mouse.y * Snake.SCALE, Snake.SCALE, Snake.SCALE);
String string = "Score: " + snake.score + ", Length: " + snake.tailLength + ", Time: " + snake.time / 20;
g.setColor(Color.white);
g.drawString(string, (int) (getWidth() / 2 - string.length() * 2.5f), 10);
string = "Game Over!";
if (snake.over)
g.drawString(string, (int) (getWidth() / 2 - string.length() * 2.5f), (int) snake.dim.getHeight() / 4);
string = "Paused!";
if (snake.paused && !snake.over)
g.drawString(string, (int) (getWidth() / 2 - string.length() * 2.5f), (int) snake.dim.getHeight() / 4);
}
}
You really shouldn't be adding a KeyListener to a JFrame. A JFrame consists of the frame, a JRootPane, which has a content pane (and now your RenderPanel) and possibly a glass pane ontop it. All of those could be stealing focus away from the frame which means it will never be able to respond to key events
KeyListener will only raise key events if the component it is registered to is focusable AND has focus.
Try using key bindings instead. They provide better control over the focus level required to generate the key event

Jumping algorithm in Java

I have made a kind of gravity in a 2D Java game and I am attempting to create a jumping algorithm. I have had a look around and cannot seen to find any help for an algorithm which moves up and down in a wave.
Here is the code in Game.java:
package game;
import java.awt.*;
public class Game extends GameLoop{
public void init(){
setSize(864,480);
Thread th = new Thread(this);
th.start();
offscreen = createImage(864,480);
d = offscreen.getGraphics();
addKeyListener(this);
}
public void paint(Graphics g){
d.clearRect(0, 0, 864, 480);
d.drawImage(background, 0, 0, this);
d.drawImage(person, x, y, this);
g.drawImage(offscreen, 0, 0, this);
}
public void update(Graphics g){
paint(g);
}
}
And here is the code in GameLoop.java:
package game;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.*;
public class GameLoop extends Applet implements Runnable, KeyListener{
public int x, y;
public Image offscreen;
public Graphics d;
public boolean up, down, left, right;
public BufferedImage background, w1, w2, w3, w4, w5, w6, w7, w8, person, s1, s2;
public int counter, counter2;
public void run(){
x = 100;
y = 100;
try {
background = ImageIO.read(new File("background.png"));
w1 = ImageIO.read(new File("walk1.png"));
w2 = ImageIO.read(new File("walk2.png"));
w3 = ImageIO.read(new File("walk3.png"));
w4 = ImageIO.read(new File("walk4.png"));
w5 = ImageIO.read(new File("walk5.png"));
w6 = ImageIO.read(new File("walk6.png"));
w7 = ImageIO.read(new File("walk7.png"));
w8 = ImageIO.read(new File("walk8.png"));
s1 = ImageIO.read(new File("stancel.png"));
s2 = ImageIO.read(new File("stancer.png"));
} catch (IOException e1) {
e1.printStackTrace();
}
person = s1;
while(true){
x = 100;
y = 100;
while(true){
if (y <= 304 && up != true){
y+=10;
}
counter++;
counter2++;
if (counter >= 20){
counter = 0;
}
if (counter >= 0 && counter <= 5 && right == true){
person = w1;
}
if (counter > 5 && counter < 10 && right == true){
person = w2;
}
if (counter >= 10 && counter <= 15 && right == true){
person = w3;
}
if (counter > 15 && right == true){
person = w4;
}
if (counter2 >= 20){
counter2 = 0;
}
if (counter2 >= 0 && counter2 <= 5 && left == true){
person = w5;
}
if (counter2 > 5 && counter2 < 10 && left == true){
person = w6;
}
if (counter2 >= 10 && counter2 <= 15 && left == true){
person = w7;
}
if (counter2 > 15 && left == true){
person = w8;
}
if (left == true){
x-=4;
}
if (right == true){
x+=4;
}
if (up == true){
y-=4;
}
if (down == true){
y+=4;
}
if ( x <= -10 ){
x = -10;
}
if ( y <= 0 ){
y = 0;
}
if ( x >= 824 ){
x = 824;
}
if ( y >= 304 ){
y = 304;
}
repaint();
try{
Thread.sleep(20);
} catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
//#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == 37){
left = true;
}
if(e.getKeyCode() == 38){
up = true;
}
if(e.getKeyCode() == 39){
right = true;
}
if(e.getKeyCode() == 40){
down = true;
}
}
//#Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == 37){
left = false;
person = s2;
}
if(e.getKeyCode() == 38){
up = false;
}
if(e.getKeyCode() == 39){
right = false;
person = s1;
}
if(e.getKeyCode() == 40){
down = false;
}
}
//#Override
public void keyTyped(KeyEvent e) {
}
}
I think I need a counter , counter3 as a double, but I am not sure of an algorithm that will go up to a certain point on the y axis, then move down. Any help is appreciated.
One of the simplest wave functions is our old friend sine:
So for a jump motion, you would probably like the first half of a sine period. You could use java.util.Math, passing a sequence of numbers from 0 to 180 (how many depends on the number of frames you want the jump to last). e.g.:
Math.sin(0.0); // = 0.0
Math.sin(30.0); // = 0.5
Math.sin(60.0); // = 0.9
Math.sin(90.0); // = 1.0
Math.sin(120.0); // = 0.9
Math.sin(150.0); // = 0.5
Math.sin(180.0); // = 0.0
I'm not entirely sure by what you mean by "moves up and down in a wave".
But anyway, in real world physics, the altitude of an object in free-fall (ignoring air resistance) follows a parabola; i.e. it obeys a formula like:
altitude = maxAltitude - (acceleration * (t - timeOfMaxAltitude))^2
(There are other ways of formulating the laws of motion, but this approach is probably what you need for a simple game.)
A 1/2 sine wave looks rather like a truncated parabola, and could be used instead in a game. However, you need to realize that it is not an accurate simulation of real-world physics, especially for high jumps.
You can use a variable to represent the vertical velocity. When you jump, set the vertical velocity to a negative value. On each frame, add the vertical velocity to the vertical position, and add a constant to the velocity to simulate gravity. When there is something underneath, set the velocity back to 0. Experiment with the constant values to get an appropriate jump height.

Trying to rewrite Snake - Snake eats itself

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);

Categories

Resources