I am making a game and the game window will only open to the size of the title. Please let me know what changes I need to make the "b.setSize(900,885)" work. I will change or add any amount of code if needed.
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;
public class Background extends JFrame implements KeyListener, ActionListener{
int platform1X = 300, platform1Y = 555, platform2X, platform2Y;
Image image;
public boolean isJumping = false;
int playerx = 100, playery = 585, velX = 0, velY = 0;
public boolean[] keyDown = new boolean[4];
private int fallingSpeed = 0;
private int gravity = 5;
private int jumpPower = -30;
public Background(){
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
keyDown[0] = false;
keyDown[1] = false;
keyDown[2] = false;
keyDown[3] = false;
}
public void paint(Graphics g){
if(!isOnGround()){
fall();
}
ImageIcon i = new ImageIcon("/Users/kairotieremorton/Documents/java code/Kairo and Enoch Game/src/images/Backgroundsquareman.png");
image = i.getImage();
g.drawImage(image, 0, 0, 900, 700, null);
g.setColor(Color.BLUE);
g.fillRect(platform1X, platform1Y, 120, 20);
g.setColor(Color.RED);
g.fillRect(playerx, playery, 30, 30);
try {
Thread.sleep(40);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
repaint();
playery = playery + velY;
playerx = playerx + velX;
}
public static void main(String[] args){
Background b = new Background();
b.setTitle("Game");
b.setSize(900,885);
b.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
b.setVisible(true);
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(isOnGround() && key == KeyEvent.VK_SPACE){
keyDown[0] = true;
jump();
}
//if(key == KeyEvent.VK_DOWN){ setvelY(5); keyDown[1] = true;}
if(key == KeyEvent.VK_LEFT) { setvelX(-5); keyDown[2] = true;}
if(key == KeyEvent.VK_RIGHT) { setvelX(5); keyDown[3] = true;}
System.out.println(key);
System.out.println(playerx);
System.out.println(playery);
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_SPACE){ keyDown[0] = false;} //tempObject.setVelY(0);
//if(key == KeyEvent.VK_DOWN) keyDown[1] = false;//tempObject.setVelY(0);
if(key == KeyEvent.VK_LEFT) keyDown[2] = false;//tempObject.setVelX(0);
if(key == KeyEvent.VK_RIGHT) keyDown[3] = false; //tempObject.setVelX(0);
//vertical movement
if(!keyDown[0]) setvelY(0); System.out.println(isOnGround());
//horizontal movement
if(!keyDown[2] && !keyDown[3]) setvelX(0);
}
public void keyTyped(KeyEvent e) {}
public void actionPerformed(ActionEvent e) {
//playery = playery + velY;
//playerx = playerx + velX;
//repaint();
}
public boolean isOnGround(){
if(playery + (30 /2) >= 585) {
return true;
}
return false;
}
public void fall(){
playery = playery + fallingSpeed;
fallingSpeed = fallingSpeed + gravity;
}
public void jump(){
fallingSpeed = jumpPower;
fall();
}
public void setvelX(int velX) {
this.velX = velX;
}
public void setvelY(int velY) {
this.velY = velY;
}
public float getvelX(){
return velX;
}
public float getvelY(){
return velY;
}
public int getplayerx(){
return playerx;
}
public int getplayery(){
return playery;
}
public void setplayerx(int playerx) {
this.playerx = playerx;
}
public void setplayery(int playery) {
this.playery = playery;
}
public Rectangle getBounds(){
return new Rectangle(getplatform1X(), platform1Y(), 120, 20);
}
public int getplatform1X(){
return platform1X;
}
public int platform1Y(){
return platform1Y;
}
public Rectangle getBoundsTop(){
return new Rectangle(getplayerx() + 10, getplayery(), 30 - 20, 5);
}
public Rectangle getBoundsBottom(){
return new Rectangle(getplayerx() + 10, getplayery() + 30 - 5, 30 - 20, 5);
}
public Rectangle getBoundsLeft(){
return new Rectangle(getplayerx(), getplayery()+10, 5, 30 -20);
}
public Rectangle getBoundsRigth(){
return new Rectangle(getplayerx() + 30 - 5, getplayery()+10, 5, 30 - 20);
}
}
Okay, that took a lot of looking, but...
public Rectangle getBounds() {
return new Rectangle(getplatform1X(), platform1Y(), 120, 20);
}
is your problem. JFrame#getBounds is a method used by JFrame to return the position and the size of the component and since you've overridden it, it will now ignore any values you pass to setSize (directly or indirectly)
Have a read of the following for reasons why you shouldn't override paint of top level containers like JFrame
How can I set in the midst?
Graphics rendering in title bar
Java JFrame .setSize(x, y) not working?
How to get the EXACT middle of a screen, even when re-sized
As a general rule of thumb, you should avoid extending from JFrame, as you're not really adding any new functionality to the class, it locks you into a single use case and, based on your experience, can cause other problems.
You should start with something like JPanel and override its paintComponent method instead (and make sure you call super.paintComponent before you do any custom painting)
Take a look at Painting in AWT and Swing and Performing Custom Painting
You paint methods should run as fast as possible, so you should avoid loading resources like loading images, within the paint method
Swing is single threaded, so calling Thread.sleep in the paint method will cause the entire program to stop, including it's ability to respond to new events from the user.
I'd also discourage you from using KeyListener, using the key bindings API will be more reliable. Take a look at How to Use Key Bindings for more details
Edit:
A better way to achieve the same result is to call b.setPreferredSize(dimension); and then pack() your frame.
See this answer for more information about JFrame.pack() :
https://stackoverflow.com/a/22982334/5224040
Try this in your main method:
public static void main(String[] args) {
Background b = new Background();
Dimension d = new Dimension(900, 885); //Create a new Dimension
b.setTitle("Game");
b.setPreferredSize(d); //Set the PreferredSize;
b.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
b.pack(); //Pack the frame
b.setVisible(true); //Setting Visible
}
You can also use the following methods to reposition your frame as necessary:
b.setLocationRelativeTo(null); //center the location on the screen.
b.setLocation(0, 0); //Set location explicitly
Call either of these methods below b.pack(); to reposition your frame.
Related
package testapplication;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class TestApplication extends JFrame implements Runnable {
int sizex = 800;
int sizey = 650;
int x, y, xDirection, yDirection;
private Image dbImage;
private Graphics dbg;
Image character;
#Override
public void run(){
try{
while(true){
move();
Thread.sleep(5);
}
}
catch(Exception e){
System.out.println("ERROR!!!");
}
}
public void move(){
x += xDirection;
y += yDirection;
if(x <= 0)
x = 0;
if(x >= 778)
x = 778;
if(y <= 22)
y = 22;
if(y >= 628)
y = 628;
}
public void setXDirection(int xdir){
xDirection = xdir;
}
public void setYDirection(int ydir){
yDirection = ydir;
}
Font font = new Font("Arial", Font.BOLD, 30);
public class AL extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
//Key press inputs "WASD"
if(keyCode == KeyEvent.VK_W) {
setYDirection(-1);
}
if(keyCode == KeyEvent.VK_A) {
setXDirection(-1);
}
if(keyCode == KeyEvent.VK_S) {
setYDirection(+1);
}
if(keyCode == KeyEvent.VK_D) {
setXDirection(+1);
}
//end Key press inputs "WASD"
}
#Override
public void keyReleased(KeyEvent e) {
int keyCode = e.getKeyCode();
//Key release inputs "WASD"
if(keyCode == KeyEvent.VK_W) {
setYDirection(0);
}
if(keyCode == KeyEvent.VK_A) {
setXDirection(0);
}
if(keyCode == KeyEvent.VK_S) {
setYDirection(0);
}
if(keyCode == KeyEvent.VK_D) {
setXDirection(0);
}
//end Key release inputs "WASD"
}
}
public TestApplication() {
//Load images
ImageIcon i = new ImageIcon("C:/Users/Min/Documents/NetBeansProjects/TestApplication/src/testapplication/Untitled-1.png") {};
character = i.getImage();
//Game properties
addKeyListener(new AL());
setTitle("TestApplication");
setSize(sizex, sizey);
setResizable(false);
setVisible(true);
setBackground(Color.LIGHT_GRAY);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
x = 30;
y = 628;
}
#Override
public void paint(Graphics g) {
dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
g.drawImage(dbImage, 0, 0, this);
}
public void paintComponent(Graphics g) {
g.setFont(font);
g.setColor(Color.RED);
g.drawString("Welcome to TESTTEST", 300,125);
g.setColor(Color.RED);
g.drawImage(character, x, y, this);
repaint();
}
public static void main(String[] args) {
TestApplication ta = new TestApplication();
//Threads
Thread t1 = new Thread();
t1.start();
}
}
In my Java code, there is supposed to be an image that moves using the WASD keys. The image shows, yet it will not move. What's wrong?
This is a simple Java code that is supposed to make an image roam around the window with WASD keys. I am not sure what I did wrong in the code, I've double checked and everything looked fine...
First of all, if you need to change the image location while the user presses one of the wsda keys then you need to add 1 and -1 to the current value of x and y ( image location). You just set 1 and -1 which will move the image just one pixel even if, for example, you press the d button multiple times over and over.
You need to change method setXDirection to this (I have added a plus before the equal sign to add xDir value to whatever xDirection is.)
public void setXDirection(int xDir)
{
xDirection += xDir
}
Make the same correction with yDirection (yDirection += yDir)
Second, you don't call your paint method. You have to call it each time your user presses a key (one of wasd ofcourse), so do it at the final line of your keyReleased method.
I hope these two correct your code but I think you need to recheck the code again with much care.
Good luck,
Iman
You forgot to add the Runnable instance to the Thread constructor.
Your main method should be:
public static void main(String[] args) {
TestApplication ta = new TestApplication();
//Threads
Thread t1 = new Thread(ta);
t1.start();
}
So I recently started playing around with java graphics and have encountered an issue. I have drawn images onto a JFrame, but did not learn that the images' bounds cannot overlap each other if they're all in one JFrame (setting bounds over where another image is makes the image disappear). I heard something about using multiple JPanels to fix this. I do not know how to do this since I used a JFrame and not a JPanel in my program, so some help would be appreciated on this issue. Thank you, and I apologize if this question is dumb. (My other question that others seem to think was the same as this one was an issue of setting bounds, this question regards bounds overlapping and covering each other)
Here are my classes:
Window Class-
package game.thirdTry;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Window extends JFrame {
private static Window instance;
public static Window getInstance() {
if(instance == null) {
instance = new Window("Game");
}
return instance;
}
private Window(String name) {
super(name);
setSize(1200, 700);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setLayout(null);
//setUndecorated(true);
addKeyListener(new UserInput());
//this.getContentPane().getSize();
WindowStructure banner = new WindowStructure("Beatles Logo.jpg", 0, 0, getWidth(), 75);
//WindowStructure fball = new WindowStructure("fireball.100x100.png", 100, 100, 100, 100);
WindowStructure fball = WindowStructure.getInstanceF();
System.out.println("Fball.xSize: " + fball.xSize + ", Fball.ySize: " + fball.ySize);
System.out.println("Fball.xLoc: " + fball.xLoc + ", Fball.yLoc: " + fball.yLoc);
//banner.setBounds(banner.xLoc, banner.yLoc, banner.xSize, banner.ySize);
//fball.setBounds(fball.xLoc, fball.yLoc, fball.xLoc + fball.xSize, fball.ySize + fball.ySize);
banner.setBounds(0, 0, getWidth(), getHeight());
fball.setBounds(0, 75, getWidth(), getHeight());
add(fball, null);
add(banner, null);
setVisible(true);
while(true){
System.out.println("Fball.xLoc: " + fball.xLoc + ", Fball.yLoc: " + fball.yLoc);
repaint();
try{
Thread.sleep(10);
}catch (Exception e){
}
}
}
/*
public void paint(Graphics g) {
super.paintComponents(g);
}
*/
}
Image Class-
package game.thirdTry;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class WindowStructure extends JPanel {
private static WindowStructure fball;
public static WindowStructure getInstanceF(){
if(fball == null){
fball = new WindowStructure("fireball.100x100.png", 0, 75, 100, 100);
}
return fball;
}
ImageIcon imageIcon;
int xLoc, yLoc, xSize, ySize;
public WindowStructure(String bannerImg, int xLoc, int yLoc, int xSize, int ySize){
URL bannerImgURL = getClass().getResource(bannerImg);
imageIcon = new ImageIcon(bannerImgURL);
this.xLoc = xLoc;
this.yLoc = yLoc;
this.xSize = xSize;
this.ySize = ySize;
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(imageIcon.getImage(), xLoc, yLoc, xSize, ySize, null);
}
}
KeyListener / User Input Class-
package game.thirdTry;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class UserInput implements KeyListener {
// Window window = Window.getInstance();
WindowStructure fball = WindowStructure.getInstanceF();
boolean goUp = false;
boolean goDown = false;
boolean goLeft = false;
boolean goRight = false;
public void moveUpDown() {
if (goUp && goDown) {
if (fball.yLoc > 0) {
fball.yLoc -= 10;
}
} else if (goUp) {
if (fball.yLoc > -5) {
fball.yLoc -= 10;
}
} else if (goDown) {
if (fball.yLoc < 480) {
fball.yLoc += 10;
}
}
System.out.println("moveUpDown() method called");
}
public void moveLeftRight() {
if (goLeft && goRight) {
if (fball.xLoc < 1100) {
fball.xLoc += 10;
}
} else if (goRight) {
if (fball.xLoc < 1110) {
fball.xLoc += 10;
}
} else if (goLeft) {
if (fball.xLoc > 0) {
fball.xLoc -= 10;
}
}
}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_W) {
goUp = true;
goDown = false;
}
if (e.getKeyCode() == KeyEvent.VK_S) {
goDown = true;
goUp = false;
}
if (e.getKeyCode() == KeyEvent.VK_A) {
goLeft = true;
goRight = false;
}
if (e.getKeyCode() == KeyEvent.VK_D) {
goRight = true;
goLeft = false;
}
moveUpDown();
moveLeftRight();
System.out.println("keyPressed() was called");
}
#Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_W) {
goUp = false;
}
if (e.getKeyCode() == KeyEvent.VK_S) {
goDown = false;
}
if (e.getKeyCode() == KeyEvent.VK_A) {
goLeft = false;
}
if (e.getKeyCode() == KeyEvent.VK_D) {
goRight = false;
}
}
#Override
public void keyTyped(KeyEvent e) {
}
}
//g2d.drawImage(imageIcon.getImage(), xLoc, yLoc, xSize, ySize, null);
The problem is that you are scaling the image as you paint the image. Therefore the image takes up the entire window space and so yes it paints over top of the image painted first.
Just paint the image at its real size:
g2d.drawImage(imageIcon.getImage(), xLoc, yLoc, this);
This is another reason to use a JLabel. You don't need to worry about the size. You just position the label at a specific location and the image will be painted. The code is much simpler. And using this approach you don't need to worry about making the panel non-opaque.
The problem with your code now is that you need to make the panel a large size because you are painting the image relative to your WindowStructure panel. So if your image is (25 x 25) and you want the image painted at (100, 100), you need to make the panel (125, 125), which means the panel need to be transparent so the part of the panel that does not contain the image is not painted. Using a JLable, the size of the label will always be (25, 25) so you simple set the location of the label and only (25, 25) pixels will be painted.
I'll look more into JLabels later
Look at it now. There is no time like the present!
Also, your WindowStructure class has a terrible design. There is no need for the static methods and variables. Each image should be independent of one another.
So I've pretty much thrown together a basic game in java by following a bunch of different tutorials - the problem is i cant manage to figure out how to get my sprite to move in different directions. Here is the code for my main
package com.game.src.main;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JFrame;
public class Game extends Canvas implements Runnable {
private static final long serialVersionUID = 1L;
public static final int WIDTH = 850;
public static final int HEIGHT = 650;
public static final int SCALE = 1;
public final String TITLE = "Racing Game!";
static ServerSocket serverSocket;
static Socket socket;
static DataOutputStream out;
private boolean running = false;
private Thread thread;
private BufferedImage image = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
private BufferedImage spriteSheet = null;
private BufferedImage spriteSheet2 = null;
private BufferedImage background = null;
private BufferedImage MenuBackground = null;
private Player p;
private Player2 p2;
private Menu menu;
public static enum STATE {
MENU,
GAME
};
public static STATE State = STATE.MENU;
public void init() {
BufferedImageLoader loader = new BufferedImageLoader();
try {
spriteSheet = loader.loadImage("/Sprite_Sheet.png");
background = loader.loadImage("/Track.png");
MenuBackground = loader.loadImage("/MenuBG.fw.png");
}
catch (IOException e) {
e.printStackTrace();
}
menu = new Menu();
addKeyListener(new KeyInput(this));
this.addMouseListener(new MouseInput());
p = new Player(365, 500, this);
p2 = new Player2(365, 550, this);
}
private synchronized void start() {
if(running)
return;
running = true;
thread = new Thread(this);
thread.start();
}
private synchronized void stop() {
if(!running)
return;
running = false;
try {
thread.join();
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.exit(1);
}
public void run() {
init();
long lastTime = System.nanoTime();
final double amountOfTicks = 60.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
int updates = 0;
int frames = 0;
long timer = System.currentTimeMillis();
while(running) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
if(delta >= 1) {
tick();
updates++;
delta--;
}
render();
frames++;
if(System.currentTimeMillis() - timer > 1000) {
timer += 1000;
System.out.println(updates + " FPS, TICKS " + frames);
updates = 0;
frames = 0;
}
}
stop();
}
private void tick() {
if(State == STATE.GAME){
p.tick();
p2.tick();
}
}
private void render() {
BufferStrategy bs = this.getBufferStrategy();
if(bs == null) {
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
g.drawImage(MenuBackground, 0, 0, null);
if(State == STATE.GAME){
//Drawing the main games background
g.drawImage(background, 0, 0, null);
p.render(g);
p2.render(g);
}
else if(State == STATE.MENU){
menu.render(g);
}
g.dispose();
bs.show();
}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
if(State == STATE.GAME){
if(key == KeyEvent.VK_RIGHT){
p.setVelX(5);
}
if(key == KeyEvent.VK_D){
p2.setVelX2(5);
}
else if(key == KeyEvent.VK_LEFT) {
p.setVelX(-5);
}
else if(key == KeyEvent.VK_A) {
p2.setVelX2(-5);
}
else if(key == KeyEvent.VK_DOWN) {
p.setVelY(5);
}
else if(key == KeyEvent.VK_S) {
p2.setVelY2(5);
}
else if(key == KeyEvent.VK_UP) {
p.setVelY(-5);
}
else if(key == KeyEvent.VK_W) {
p2.setVelY2(-5);
}
}
}
public void keyReleased(KeyEvent e){
int key = e.getKeyCode();
if(key == KeyEvent.VK_RIGHT){
p.setVelX(0);
}
if(key == KeyEvent.VK_D){
p2.setVelX2(0);
}
else if(key == KeyEvent.VK_LEFT) {
p.setVelX(0);
}
else if(key == KeyEvent.VK_A) {
p2.setVelX2(0);
}
else if(key == KeyEvent.VK_DOWN) {
p.setVelY(0);
}
else if(key == KeyEvent.VK_S) {
p2.setVelY2(0);
}
else if(key == KeyEvent.VK_UP) {
p.setVelY(0);
}
else if(key == KeyEvent.VK_W) {
p2.setVelY2(0);
}
}
public static void main(String args[]) throws Exception {
Game game = new Game();
game.setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
game.setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
game.setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
JFrame frame = new JFrame(game.TITLE);
frame.add(game);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
game.start();
System.out.println("Starting server....");
serverSocket = new ServerSocket(7777);
System.out.println("Server started");
socket = serverSocket.accept();
System.out.println("Connecting from: " + socket.getInetAddress());
out = new DataOutputStream(socket.getOutputStream());
out.writeUTF("This is a test of Java Sockets");
System.out.println("Data has been sent");
}
public BufferedImage getSpriteSheet() {
return spriteSheet;
}
public BufferedImage getSpriteSheet2() {
return spriteSheet2;
}
}
This is my player class
package com.game.src.main;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
public class Player {
private double x;
private double y;
private double velX = 0;
private double velY = 0;
private BufferedImage player;
BufferedImageLoader loader = new BufferedImageLoader();
BufferedImage SpriteSheet = null;
public Player(double x, double y, Game game) {
this.x = x;
this.y = y;
//New instance of Sprite sheet - reading from buffered image loader
SpriteSheet ss = new SpriteSheet(game.getSpriteSheet());
player = ss.grabImage(1, 1, 50, 50);
try {
SpriteSheet = loader.loadImage("/Sprite_Sheet.png");
}
catch(Exception e) {
e.printStackTrace();
}
}
public void tick() {
x+=velX;
y+=velY;
//Adding basic collision
if(x < 0 + 50) {
x = 0 + 50;
}
if(x >= 850 - 100) {
x = 850 - 100;
}
if(y < 0 + 100) {
y = 0 + 100;
}
if(y >= 650 - 100){
y = 650 - 100;
}
}
public void render(Graphics g){
//Draw Track
Color c1 = Color.green;
g.setColor( c1 );
g.fillRect( 150, 200, 550, 300 ); //grass
Color c2 = Color.black;
g.setColor( c2 );
g.drawRect(50, 100, 750, 500); // outer edge
g.drawRect(150, 200, 550, 300); // inner edge
Color c3 = Color.yellow;
g.setColor( c3 );
g.drawRect( 100, 150, 650, 400 ); // mid-lane marker
Color c4 = Color.white;
g.setColor( c4 );
g.drawLine( 425, 500, 425, 600 ); // start line
g.drawImage(player, (int)x, (int)y, null);
}
public double getX(Graphics g){
return x;
}
public double getY(){
return y;
}
public void setX(double x){
this.x = x;
}
public void setY(double y){
this.y = y;
}
public void setVelX(double velX){
this.velX = velX;
}
public void setVelY(double velY){
this.velY = velY;
}
}
I have two players in this game but i'm really stuck on how i can change the sprites direction by 22.5% in a desired direction so if i pressed the up key for player 1 it would rotate my car 22.5% north etc. I have a sprite sheet with 16 sprites for each player for every change in angle by 22.5% This is really confusing me and i'm not sure how i can implement this,
Thanks for taking the time to look
This is a basic example of spinning a sprite
What this is maintain's a virtual state which the Player object inspects in order to determine how it should be changed accordingly. This separates the action from the result, meaning that it would be possible to substitute the action (arrow up key) with some other action, but still obtain the same result.
This example also uses the key bindings API, which doesn't suffer from the same focus related issues that KeyListener does, but this is a pure Swing API and won't be compatiable with Canvas, but is a nice demonstration ;)
The real magic occurs in the characters paint method...
public void paint(Graphics2D g2d) {
Graphics2D g = (Graphics2D) g2d.create();
AffineTransform at = new AffineTransform();
at.translate(x, y);
at.rotate(Math.toRadians(angle), character.getWidth() / 2, character.getHeight() / 2);
g.transform(at);
g.drawImage(character, 0, 0, null);
}
Basically, this creates a AffineTransformation which is then compounded to produce the result we need. That is, first it's anchor position is translated to the characters x/y position and then rotated about the characters center point. Because it's been translated, we can simply paint the character at 0x0. This much easier then try to calculate the characters rotation anchor somewhere else in virtual space - IMHO
The character is rotated by pressing either the Up or Down arrow keys. While pressed, the character will continue to rotate, this is a feature of the example for demonstration purpose.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class RotateCharater {
public static void main(String[] args) {
new RotateCharater();
}
public RotateCharater() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private DefaultState state;
private Player player;
public TestPane() {
player = new Player();
state = new DefaultState();
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "upKeyPressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "upKeyReleased");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "downKeyPressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "downKeyReleased");
ActionMap am = getActionMap();
am.put("upKeyPressed", new UpKeyAction(state, true));
am.put("upKeyReleased", new UpKeyAction(state, false));
am.put("downKeyPressed", new DownKeyAction(state, true));
am.put("downKeyReleased", new DownKeyAction(state, false));
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
player.update(state);
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
player.paint(g2d);
g2d.dispose();
}
public class UpKeyAction extends AbstractAction {
private DefaultState state;
private boolean pressed;
public UpKeyAction(DefaultState state, boolean pressed) {
this.state = state;
this.pressed = pressed;
}
#Override
public void actionPerformed(ActionEvent e) {
state.setUpKeyPressed(pressed);
}
}
public class DownKeyAction extends AbstractAction {
private DefaultState state;
private boolean pressed;
public DownKeyAction(DefaultState state, boolean pressed) {
this.state = state;
this.pressed = pressed;
}
#Override
public void actionPerformed(ActionEvent e) {
state.setDownKeyPressed(pressed);
}
}
}
public interface State {
public boolean isUpKeyPressed();
public boolean isDownKeyPressed();
}
public class DefaultState implements State {
private boolean upKeyPressed;
private boolean downKeyPressed;
public boolean isDownKeyPressed() {
return downKeyPressed;
}
public boolean isUpKeyPressed() {
return upKeyPressed;
}
public void setDownKeyPressed(boolean downKeyPressed) {
this.downKeyPressed = downKeyPressed;
upKeyPressed = false;
}
public void setUpKeyPressed(boolean upKeyPressed) {
this.upKeyPressed = upKeyPressed;
downKeyPressed = false;
}
}
public class Player {
private BufferedImage character;
private int x = 100 - 32, y = 100 - 32;
private double angle;
public Player() {
try {
character = ImageIO.read(getClass().getResource("/Character.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void paint(Graphics2D g2d) {
Graphics2D g = (Graphics2D) g2d.create();
AffineTransform at = new AffineTransform();
at.translate(x, y);
at.rotate(Math.toRadians(angle), character.getWidth() / 2, character.getHeight() / 2);
g.transform(at);
g.drawImage(character, 0, 0, null);
}
public void update(State state) {
if (state.isUpKeyPressed()) {
angle -= 22.5;
} else if (state.isDownKeyPressed()) {
angle += 22.5;
}
}
}
}
Remember, this is just an example used to present the concept ;)
I created an oval which shoots a bullet(rectangle) that if it hits the red rectangle, the collision would detect the bullet hitting the rectangle. However, when I run my program, the collision has already been done and I haven't even pressed the space bar yet to shoot. What I wanted to happen is that, when I shoot and if the bullet hits the rectangle, that's when it detects the collision. I tried to analyze it and do something but I just couldn't get it. here is my source code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class JavaGame2 extends JPanel implements KeyListener,Runnable{
//variables
JFrame frame;
int x, y, xDir, yDir,bx,by;
Rectangle bullet;
boolean readyTofire, shot = false;
//constructor for game
public JavaGame2(){
frame = new JFrame("Java Game");
int x=150;
int y=150;
}
//drawings
public void paintComponent(Graphics g){
super.paintComponent(g);
this.setBackground(Color.WHITE);
Rectangle rec = new Rectangle(50, 20, 50, 50);
g.setColor(Color.BLUE);
g.fillOval(x, y, 55, 55);
g.fillRect(x+23, y-15, 10, 20);
g.setColor(Color.RED);
g.fillRect(rec.x, rec.y, rec.width, rec.height);
bullet = new Rectangle(bx, by, 5, 3);
if(shot){
g.setColor(Color.BLACK);
g.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
}
if(bullet.intersects(rec));
g.drawString("collision!", 50, 20);
repaint();
}
public void setxDir(int xdir){
xDir = xdir;
}
public void setyDir(int ydir){
yDir = ydir;
}
//key event listener keypressed
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if(code == KeyEvent.VK_UP){
setyDir(-1);
}
if(code == KeyEvent.VK_DOWN){
setyDir(+1);
}
if(code == KeyEvent.VK_LEFT){
setxDir(-1);
}
if(code == KeyEvent.VK_RIGHT){
setxDir(+1);
}
if(code == KeyEvent.VK_SPACE){
if(bullet == null ){
readyTofire = true;
if(readyTofire){
bx = x+26;
by = y-15;
bullet = new Rectangle(bx, by, 5, 3);
shot = true;
}
}
}
}
//key event listener for key released
public void keyReleased(KeyEvent e) {
int code = e.getKeyCode();
if(code == KeyEvent.VK_UP){
setyDir(0);
}
if(code == KeyEvent.VK_DOWN){
setyDir(0);
}
if(code == KeyEvent.VK_LEFT){
setxDir(0);
}
if(code == KeyEvent.VK_RIGHT){
setxDir(0);
}
if(code == KeyEvent.VK_SPACE){
readyTofire = false;
if(bullet.y <= -5){
bullet = new Rectangle(0, 0, 0, 0);
shot = false;
readyTofire = true;
}
}
}
public void keyTyped(KeyEvent e) {
}
//shot of bullet
public void shoot(){
if(shot){
bullet.y--;
}
}
//movement of the oval
public void move(){
x += xDir;
y += yDir;
if(x <= 0){
x = 0;
}
else if(x >= 500){
x = 500;
}
else if(y <= 0){
y = 0;
}
else if(y >= 500){
y = 500;
}
}
//thread
public void run() {
try{
while(true){
shoot();
move();
Thread.sleep(5);
}
}
catch(Exception e){
System.out.println("error!");
}
}
}
Take a moment to have a look at you collision detection statement...
if (bullet.intersects(rec));
g.drawString("collision!", 50, 20);
The problem is, you've ended your if statement with a ;
if (bullet.intersects(rec));
^---
This means that the statement is effectively ignored, it would be the same as...
if (bullet.intersects(rec)) {
}
g.drawString("collision!", 50, 20);
Which would have alerted you to the problem in the first place
Instead, try using
if (bullet.intersects(rec)) {
g.drawString("collision!", 50, 20);
}
Now, don't call repaint or any method that might call repaint (like setBackground) from any paint method. This will set up a cycle of repeated paint events that will eventually consume your CPU.
I don't think you really need 200fps and Thread.sleep of roughly 40 would give you 25fps and would typically be more then adequate for your purposes.
You should also consider using key bindings, which will allow you to over come the focus related issues of KeyListener.
I'd also encourage you to explore the use of a Swing Timer which will reduce the possibility of un-synchorised updates between the model and the view, which could cause random and difficult to solve artificates or other issues...
Shooting Problems
There's a bunch of logic issues and mis-use of variables...
To start with...
Remove bx and by, you don't need them. You actually don't really need x and y either, but that might be come a little more apparent as we go...
Don't create bullet in paintComponent, this is causing some confusion...
You may not need the keyReleased check of VK_SPACE but if you did, you should set shot to false and bullet to null...
Setting readyToFire to true right before you check to see if it's true seems weird...however, when you detect a VK_SPACE in keyPressed check to see if bullet is null or not, if it's not, then a bullet already exist, don't know if this is an issue, but if you were to use a List, you could have multiple bullets firing at the same time...any way, create a new Rectangle and assign to to bullet
if (code == KeyEvent.VK_SPACE) {
readyTofire = true;
if (readyTofire) {
int bx = x + 26;
int by = y - 15;
bullet = new Rectangle(bx, by, 5, 3);
shot = true;
}
}
In you shoot method, do forget to do a bounds check...
public void shoot() {
if (shot) {
bullet.y--;
// Have we past the edge of the screen
if (bullet.y < 0) {
shot = false;
bullet = null;
}
}
}
And finally, paint it all...Here you should be taking advantage of the 2D Graphics API
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Rectangle rec = new Rectangle(50, 20, 50, 50);
g.setColor(Color.BLUE);
g.fillOval(x, y, 55, 55);
g.fillRect(x + 23, y - 15, 10, 20);
g.setColor(Color.RED);
g.fillRect(rec.x, rec.y, rec.width, rec.height);
if (shot && bullet != null) {
g2d.setColor(Color.BLACK);
g2d.fill(bullet);
if (bullet.intersects(rec)) {
g2d.drawString("collision!", 50, 20);
}
}
g2d.dispose();
}
And in case I missed anything, here's you the code I tested with...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class JavaGame2 extends JPanel implements KeyListener, Runnable {
//variables
int x, y, xDir, yDir;
Rectangle bullet;
boolean readyTofire, shot = false;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JavaGame2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
//constructor for game
public JavaGame2() {
int x = 150;
int y = 150;
this.setBackground(Color.WHITE);
setFocusable(true);
addKeyListener(this);
requestFocusInWindow();
Thread t = new Thread(this);
t.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
//drawings
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Rectangle rec = new Rectangle(50, 20, 50, 50);
g.setColor(Color.BLUE);
g.fillOval(x, y, 55, 55);
g.fillRect(x + 23, y - 15, 10, 20);
g.setColor(Color.RED);
g.fillRect(rec.x, rec.y, rec.width, rec.height);
if (shot && bullet != null) {
g2d.setColor(Color.BLACK);
g2d.fill(bullet);
if (bullet.intersects(rec)) {
g2d.drawString("collision!", 50, 20);
}
}
g2d.dispose();
}
public void setxDir(int xdir) {
xDir = xdir;
}
public void setyDir(int ydir) {
yDir = ydir;
}
//key event listener keypressed
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP) {
setyDir(-1);
}
if (code == KeyEvent.VK_DOWN) {
setyDir(+1);
}
if (code == KeyEvent.VK_LEFT) {
setxDir(-1);
}
if (code == KeyEvent.VK_RIGHT) {
setxDir(+1);
}
if (code == KeyEvent.VK_SPACE) {
readyTofire = true;
if (readyTofire) {
int bx = x + 26;
int by = y - 15;
bullet = new Rectangle(bx, by, 5, 3);
shot = true;
}
}
}
//key event listener for key released
public void keyReleased(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP) {
setyDir(0);
}
if (code == KeyEvent.VK_DOWN) {
setyDir(0);
}
if (code == KeyEvent.VK_LEFT) {
setxDir(0);
}
if (code == KeyEvent.VK_RIGHT) {
setxDir(0);
}
// if (code == KeyEvent.VK_SPACE) {
// readyTofire = false;
// if (bullet.y <= -5) {
// bullet = new Rectangle(0, 0, 0, 0);
// shot = false;
// readyTofire = true;
//
// }
// }
}
public void keyTyped(KeyEvent e) {
}
//shot of bullet
public void shoot() {
if (shot) {
bullet.y--;
if (bullet.y < 0) {
shot = false;
bullet = null;
}
}
}
//movement of the oval
public void move() {
x += xDir;
y += yDir;
if (x <= 0) {
x = 0;
} else if (x >= 500) {
x = 500;
} else if (y <= 0) {
y = 0;
} else if (y >= 500) {
y = 500;
}
}
//thread
public void run() {
try {
while (true) {
shoot();
move();
repaint();
Thread.sleep(40);
}
} catch (Exception e) {
System.out.println("error!");
}
}
}
No offense, but you approach is a little primitive. Instead of containing the entire game model within the same class that is trying to display it, you should separate your game "logic" into a model and update the model state and then simply have your view paint the model...IMHO
I need help trying to sort how this collision detection in my code.
Here is my code and I have had a little assistance from various sources online but nothing with a definite explanation to it yet, but all in all I have made a lot of progress. So basically a quick thank you internet.
What I have to do is make a game where I control an object, in this case a blue circle and then touch another on screen object, in this case a yellow circle and when they touch the yellow circle will dissapear and the word "YUM" will take its place then the yellow circle will move randomly to a new location.
This is a lot like the game snake but I can't get the collision to work right and also if I did have it working I have no idea how I would update the location to a new location randomly on the screen.
here is the code:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;
import javax.swing.JFrame;
import org.w3c.dom.css.Rect;
public class javagame2 extends JFrame {
private Image dbimage;
private Graphics dbg;
Font font = new Font("Arial", Font.BOLD, 30);
static Random generator = new Random();
static int randomIndex0 = generator.nextInt(900);
static int randomIndex1 = generator.nextInt(400);
public static class player
{
static int x = 150;
static int y = 150;
static final int Width = 50;
static final int Height = 50;
}
public static class pizza
{
static final int x1 = randomIndex0;
static final int y1 = randomIndex1;
int Width = 50;
int Height = 50;
public boolean intercepts(player p) {
// TODO Auto-generated method stub
return false;
}
}
public class AL extends KeyAdapter
{
public void keyPressed(KeyEvent e)
{
int keycode = e.getKeyCode();
if(keycode == e.VK_LEFT){
if(player.x <= 0)
{
player.x = 0;
}
else
{
player.x += -10;
}
}
if(keycode == e.VK_RIGHT){
if(player.x >= 950)
{
player.x = 950;
}
else
{
player.x += 10;
}
}
if(keycode == e.VK_UP){
if(player.y <= 20)
{
player.y = 20;
}
else
{
player.y += -10;
}
}
if(keycode == e.VK_DOWN){
if(player.y >= 450)
{
player.y = 450;
}
else
{
player.y += 10;
}
}
}
public void keyReleased(KeyEvent e){}
}
public int getX()
{
return player.x;
}
public int getY()
{
return player.y;
}
/*
public boolean collide(pizza f)
{
if(f.X <= (player.x+40) && f.Y >= (player.y+40))
{
System.out.println("they collided");
return true;
}
else
{
return false;
}
}
*/
public boolean collide(pizza f, player p)
{
if(f.x1 <= p.x && f.y1 >= p.y)
{
System.out.println("they collided");
return true;
}
else
{
return false;
}
}
public javagame2()
{
addKeyListener(new AL());
setTitle("Ballon Popper");
setSize(1000, 500);
setResizable(false);
setVisible(true);
setBackground(Color.BLACK);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void paintcomponent(Graphics g)
{
g.setColor(Color.WHITE);
g.drawRect(pizza.x1, pizza.y1, 50, 50);
g.setFont(font);
g.setColor(Color.RED);
g.drawString("Eat the Pizza!", 350, 50);
g.setColor(Color.BLUE);
g.drawRect(getX(), getY(), 50, 50);
g.fillOval(getX(), getY(), 50, 50);
g.setColor(Color.YELLOW);
g.fillOval(pizza.x1, pizza.y1, 50, 50);
repaint();
}
public void paint(Graphics g)
{
dbimage = createImage(getWidth(), getHeight());
dbg = dbimage.getGraphics();
paintcomponent(dbg);
g.drawImage(dbimage, 0, 0, this);
}
public static void main(String arg[])
{
new javagame2();
}
}
Here is the updated code I just worked out a little bit, it does run but I'm a bit confused on how to go about removing the yellow circle once I have touched or even what to do, I tried using .intersects but that didn't seem to do anything.
I don't know java, but this seems straightforward.
Two circles collide when the distance between their centers is less than the sum of their radii. (And if the circles are the same size, we needn't worry about whether their "locations" are actually at their centers or not.)
public boolean collide(pizza f, player p)
{
if(Math.pow(f.x1-p.x, 2) + Math.pow(f.y1-p.y, 2) <= Math.pow(f.Width/2 + p.Width/2, 2))
{
System.out.println("they collided");
return true;
}
else
{
return false;
}
}