I'm trying to change the background of my little programm as soon as someone hits space (32). It just won't work and I have been trying different things and everything I could find on the internet like putting the g.setColor(Color.BLUE);
at the beginning of the public void paintComponent(Graphics g)block.
Here I got the following code.
My Screen.java
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Screen extends JPanel implements Runnable{
Thread thread = new Thread(this);
Frame frame;
private int fps = 0;
public int scene = 0;
public boolean running = false;
public Screen(Frame frame){
this.frame = frame;
this.frame.addKeyListener(new KeyHandler(this));
thread.start();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
super.paint(g);
g.clearRect(0, 0, this.frame.getWidth(),this.frame.getHeight());
g.drawString(fps + "", 10, 10);
if (scene == 0) {
g.setColor(Color.BLUE);
} else if (scene == 1) {
g.setColor(Color.GREEN);
} else {
g.setColor(Color.white);
}
g.fillRect(0, 0, getWidth(), getHeight());
}
public void run() {
System.out.println("[Success] Frame Created!");
long lastFrame = System.currentTimeMillis();
int frames = 0;
running = true;
scene = 0;
while(running){
repaint();
frames++;
if(System.currentTimeMillis() - 1000 >= lastFrame){
fps = frames;
frames = 0;
lastFrame = System.currentTimeMillis();
}
try {
Thread.sleep(2);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
System.exit(0);
}
public class KeyTyped{
public void keySPACE() {
scene = 1;
}
public void keyESC(){
running = false;
}
}
}
KeyHandler.java
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class KeyHandler implements KeyListener {
public Screen screen;
public Screen.KeyTyped keyTyped;
public KeyHandler(Screen screen){
this.screen = screen;
this.keyTyped = this.screen.new KeyTyped();
}
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
System.out.println(keyCode);
if(keyCode == 27){
this.keyTyped.keyESC();
}
if(keyCode == 32){
this.keyTyped.keySPACE();
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
}
I don't know why the code isn't in one block. Seems like I'm doing something wrong with it?
You should use InputMap / ActionMap instead of a KeyListener
You need to make sure the JComponent is set to isFocusable(true), and you do component.requestFocus() when first shown to make sure that your action will trigger.
please do the corrections:
1. use JFrame instead of Frame
2. implemement paintComponent like this:
g.clearRect(0, 0, this.frame.getWidth(),this.frame.getHeight());
if (scene == 0) {
g.setColor(Color.BLUE);
} else if (scene == 1) {
g.setColor(Color.GREEN);
} else {
g.setColor(Color.white);
}
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.WHITE);
g.drawString(fps + "", 10, 10);
3. make sure Screen is added JFrame
4. make sure to issue setVisible(true) on JFrame
Related
For some reason, my KeyListener works just fine and fires off the Booleans to make down and up true and false and the y value changes according to those Booleans exactly how I want it to. My problem is that for some reason, the red rectangle appears to grow in size rather than move, and I'm pretty sure that it's because the previous frame is not cleared. I tried to use super.paintComponent(g); to clear the frame but this accomplishes nothing. Here's the code:
JFrame:
import java.awt.*;
import javax.swing.*;
public class H extends JFrame
{
public H()
{
super("Atlas Blade");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
pack();
P p = new P();
Insets frameInsets = getInsets();
int frameWidth = p.getWidth() +
(frameInsets.left + frameInsets.right);
int frameHeight = p.getHeight() + (
frameInsets.top + frameInsets.bottom);
setPreferredSize(new Dimension(frameWidth, frameHeight));
setLayout(null);
add(p);
pack();
setVisible(true);
}
}
JPanel:
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.awt.image.*;
public class P extends JPanel implements KeyListener, Runnable
{
private long updateCount=0;
private long paintCount=0;
private int updatesPerSecond = 50;
private boolean aLeft,aRight,aDown,aUp=false;
private boolean up,down,left,right=false;
int x = 20;
int y=20;
Hb box = new Hb(x,y);
Rectangle rect = new Rectangle(0,300,300,50);
BufferedImage buffer;
public P()
{
super();
setSize(600,350);
//setSize(50,50);
buffer = new BufferedImage (600,350,BufferedImage.TYPE_4BYTE_ABGR);
addKeyListener(this);
Thread jim = new Thread(this);
jim.start();
}
public void run()
{
int waitToUpdate = 1000/updatesPerSecond;
long startTime = System.nanoTime();
while(true)
{
boolean shouldRepaint = false;
long currentTime = System.nanoTime();
long updatesNeeded = (((currentTime-startTime) / 1000000))/ waitToUpdate;
for(long x = updateCount; x< updatesNeeded; x++)
{
updateGame();
shouldRepaint=true;
updateCount++;
}
if(shouldRepaint)
{
paintCount++;
repaint();
}
try
{
Thread.sleep(5);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics bg = buffer.getGraphics();
bg.setColor(Color.BLACK);
bg.drawRect(0,300,300,50);
bg.setColor(Color.RED);
bg.fillRect(x,y,35,35);
g.drawImage(buffer,0,0,null);
}
public void updateGame()
{
box.updateHitbox(x,y);
if(down)
{
if(!box.center.intersects(rect))
{
y++;
//y=y+40;
}
}
else if(up)
{
if(!box.center.intersects(rect))
{
y--;
}
}
}
public void keyPressed(KeyEvent e)
{
int code = e.getKeyCode();
if(code==KeyEvent.VK_A)
{
left=true;
right=false;
aLeft=true;
aRight=false;
aDown=false;
aUp=false;
}
if(code==KeyEvent.VK_D)
{
left=false;
right=true;
aLeft=false;
aRight=true;
aDown=false;
aUp=false;
}
if(code==KeyEvent.VK_S)
{
System.out.println(y);
down=true;
up=false;
aLeft=false;
aRight=false;
aDown=true;
aUp=false;
}
if(code==KeyEvent.VK_W)
{
down=false;
up=true;
aLeft=false;
aRight=false;
aDown=false;
aUp=true;
}
repaint();
}
public void keyTyped(KeyEvent e)
{
}
public void keyReleased(KeyEvent e)
{
int code = e.getKeyCode();
if(code==e.VK_A)
{
left=false;
aLeft=false;
}
if(code==e.VK_D)
{
right=false;
aRight=false;
}
if(code==e.VK_S)
{
down=false;
aDown=false;
}
if(code==e.VK_W)
{
up=false;
aUp=false;
}
}
public void addNotify()
{
// call super so the method still does what it was built to do
super.addNotify();
// requests focus so that key inputs are sent to this screen
requestFocus();
}
}
And the Hb class:
import java.awt.Rectangle;
public class Hb
{
public Rectangle center,left,right,up,down;
public Hb(int x, int y)
{
center = new Rectangle(x,y,50,50);
left = new Rectangle(x-1,y+1,1,48);
right = new Rectangle(x+50,y+1,1,48);
up = new Rectangle(x+1,y-1,48,1);
down = new Rectangle(x+1,y+50,48,1);
}
public void updateHitbox(int x, int y)
{
center = new Rectangle(x,y,50,50);
left = new Rectangle(x-1,y+1,1,48);
right = new Rectangle(x+50,y+1,1,48);
up = new Rectangle(x+1,y-1,48,1);
down = new Rectangle(x+1,y+50,48,1);
}
}
Your problem is that you're doing all your drawing in the BufferedImage, and that doesn't allow erasure of "dirty" pixels. Instead, only draw in the BufferedImage that which should be a static and unchanging part of the image, usually the background. The foreground image that moves should be painted directly in paintComponent using the Graphcis object given to the method by the JVM.
public P() {
super();
setSize(600, 350); // not recommended
buffer = new BufferedImage(600, 350, BufferedImage.TYPE_4BYTE_ABGR);
Graphics bg = buffer.getGraphics();
bg.setColor(Color.BLACK);
bg.drawRect(0, 300, 300, 50);
bg.dispose();
// ....
}
and
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(buffer, 0, 0, null);
g.setColor(Color.RED);
g.fillRect(x, y, 35, 35);
}
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.
My code below is for a checkers program. If the user either clicks on a stop button or holds the mouse, it stops, and the go button or mouse release moves the checkers from the beginning.
I am not able to figure out how to move the checkers from the same position that they were stopped at. Help Please!
import java.awt.Button;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class Checkers extends java.applet.Applet implements Runnable,
ActionListener {
Thread runner;
int xpos;
Image offscreenImg;
Graphics offscreenG;
Button goButton, stopButton, exitButton;
private ExitButtonHandler ebHandler;
public void init() {
// offscreenImg = createImage(getWidth(), getHeight());
offscreenImg = createImage(this.size().width, this.size().height);
offscreenG = offscreenImg.getGraphics();
setSize(200, 250);
addMouseListener(new Mouse());
goButton = new Button("Go");
goButton.setBounds(10, 200, 90, 20);
setLayout(null);
stopButton = new Button("Stop");
stopButton.setBounds(100, 200, 90, 20);
setLayout(null);
exitButton = new Button("Exit");
ebHandler = new ExitButtonHandler();
exitButton.addActionListener(ebHandler);
exitButton.setBounds(55, 220, 90, 20);
setLayout(null);
add(goButton);
add(stopButton);
add(exitButton);
stopButton.addActionListener(this);
goButton.addActionListener(this);
}
public void start() {
if (runner == null) {
runner = new Thread(this);
runner.start();
}
}
public void stop() {
if (runner != null) {
runner.stop();
runner = null;
}
}
public void run() {
while (true) {
for (xpos = 5; xpos <= 105; xpos += 4) {
repaint();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
xpos = 5;
for (xpos = 105; xpos >= 5; xpos -= 4) {
repaint();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
xpos = 5;
}
}
public void update(Graphics g) {
paint(g);
}
public void paint(Graphics g) {
// Draw background onto the buffer area
offscreenG.setColor(Color.blue);
offscreenG.fillRect(0, 0, 100, 100);
offscreenG.setColor(Color.red);
offscreenG.fillRect(0, 100, 100, 100);
offscreenG.setColor(Color.red);
offscreenG.fillRect(100, 0, 100, 100);
offscreenG.setColor(Color.blue);
offscreenG.fillRect(100, 100, 100, 100);
// Draw checker
offscreenG.setColor(Color.green);
offscreenG.fillOval(xpos, 5, 90, 90);
offscreenG.setColor(Color.yellow);
offscreenG.fillOval(-xpos + 110, 105, 90, 90);
// Now, transfer the entire buffer onto the screen
g.drawImage(offscreenImg, 0, 0, this);
}
public void destroy() {
offscreenG.dispose();
}
// Mouse events
public class Mouse extends MouseAdapter {
public void mousePressed(MouseEvent e) {
stop();
}
public void mouseReleased(MouseEvent e) {
start();
}
}
// Button events
public void actionPerformed(ActionEvent e) {
if (e.getSource() == stopButton) {
stop();
} else if (e.getSource() == goButton) {
start();
}
}
// exit button
public class ExitButtonHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
}
You are recreating a new Thread which starts from the beginning every time you call the start function. Also, after you call stop you will not be able to "resume" where you left off.
You will want to change your Thread to use a flag of some type (boolean stopped;) and then change that flag when you call stop and start, so the Thread doesn't actually end but just "pauses." (stops moving, but is actually still running)
if (stopped) {
//dont do stuff
}
else {
//do stuff
}
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'm developing a very simple version of R-Type as work for the university, but despite it works, the craft velocity is a lot of slow, so the movement is ugly and clumsy.
I use the method repaint for refresh the screen, there are others methods or ways best than it?
Video of Movement
Paint method at main Panel
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.drawImage(fondo, 0, 0,1200,600,this);
pj.paint(g2);
g2D=g2;
}
PJ's paint method
public void paint(Graphics2D g) {
g.drawImage(imagen,x,y,this);
}
PJ's move method
public void move (KeyEvent e) {
int dx = 0; int dy = 0;
int code = e.getKeyCode();
switch (code) {
case KeyEvent.VK_Q: dy-=1; break;
case KeyEvent.VK_A: dy+=1; break;
case KeyEvent.VK_P: dx+=1; break;
case KeyEvent.VK_O: dx-=1; break;
}
int x = (getX()<maxX&&getX()!=0) ? getX()+dx : getX();
int y = (getY()<maxY&&getY()!=0) ? getY()+dy : getY();
if (getY()>=maxY||getY()==0) {
if (dy==+1) y=y+1;
}
setPosicion(x, y);
}
The image fondo should already be scaled to 1200x600.
I am not sure, but is super.paint(g) needed? You might also use paintComponent.
The event handling (you seem to be moving by 1 pixel on key down), must be done correctly. I would have set the direction and speed (1px), and leave it to a swing timer to do the continuous moving.
Repainting best is done resilient/flexible: repaint(20L) (50 frames per second);
events like key-down maybe with EventQueue.invokeLater(new Runnable() { ... });.
Especially you might use repaint with the changed area.
You can find a great example of a similar program here. The example demonstrates creating a new thread and having that thread sleep every iteration through the main loop.
Here is another question about loading images for games in Java.
It looks like swing itself is pretty crummy for using images in games. You may want to consider using a more suitable library.
Below is simple example using a background as simple game loop. It updates the state of the game objects and calculates the required delay in order to maintain the required fps.
The game object (Ship) has the ability to accelerate/decelerate over a short period of time
import java.awt.BorderLayout;
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.KeyEvent;
import java.awt.geom.Path2D;
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.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class AnimationTest {
public static void main(String[] args) {
new AnimationTest();
}
public AnimationTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new GamePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class GamePane extends JPanel {
private Ship ship;
public GamePane() {
ship = new Ship();
Thread thread = new Thread(new MainLoop(this));
thread.setDaemon(true);
thread.start();
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
// Key controls...
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "upPressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "downPressed");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "upReleased");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "downReleased");
am.put("upPressed", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// Change the direction...
ship.setDirection(-1);
// Accelerate by 1 per frame
ship.setVelocity(1);
}
});
am.put("downPressed", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// Change direction
ship.setDirection(1);
// Accelerate by 1 per frame
ship.setVelocity(1);
}
});
am.put("upReleased", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// Deccelerate by 1 per frame
ship.setVelocity(-1);
}
});
am.put("downReleased", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// Deccelerate by 1 per frame
ship.setVelocity(-1);
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public void updateState() {
// Update the state of the game objects.
// This would typically be better done in
// some kind of model
ship.update(getWidth(), getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// Paint the game state...
Graphics2D g2d = (Graphics2D) g.create();
ship.paint(g2d);
g2d.dispose();
}
}
public class MainLoop implements Runnable {
private GamePane pane;
private int fps = 25;
public MainLoop(GamePane pane) {
this.pane = pane;
}
#Override
public void run() {
// Wait until the screen is ready
while (pane.getHeight() <= 0) {
try {
Thread.sleep(125);
} catch (InterruptedException ex) {
}
}
// Main loop
while (true) {
// Start time loop
long startTime = System.currentTimeMillis();
// Update the game state
pane.updateState();
// Calculate the amount of time it took to update
long elasped = System.currentTimeMillis() - startTime;
// Calculate the number of milliseconds we need to sleep
long sleep = Math.round((1000f / fps) - elasped);
pane.repaint();
if (sleep > 0) {
try {
Thread.sleep(sleep);
} catch (InterruptedException ex) {
}
}
}
}
}
public static class Ship {
public static int MAX_SPEED = 8;
private int direction = 0;
private int velocity = 0;
private int x;
private int y;
private int speed = 0;
private Path2D shape;
private boolean initState;
public Ship() {
shape = new Path2D.Float();
shape.moveTo(0, 0);
shape.lineTo(5, 5);
shape.lineTo(0, 10);
shape.lineTo(0, 0);
shape.closePath();
initState = true;
}
public void setDirection(int direction) {
this.direction = direction;
}
public void setVelocity(int velocity) {
this.velocity = velocity;
}
public void update(int width, int height) {
if (initState) {
y = (height - 10) / 2;
initState = false;
} else {
// Add the velocity to the speed
speed += velocity;
// Don't over accelerate
if (speed > MAX_SPEED) {
speed = MAX_SPEED;
} else if (speed < 0) {
speed = 0;
}
// Adjust out position if we're moving
if (speed > 0) {
y += (direction * speed);
}
// Bounds check...
if (y - 5 < 0) {
y = 5;
} else if (y + 5 > height) {
y = height - 5;
}
}
}
public void paint(Graphics2D g2d) {
int yPos = y - 5;
g2d.translate(10, yPos);
g2d.fill(shape);
g2d.translate(-10, -yPos);
}
}
}