Hey I'm trying to create a video game and I'm testing to see if I can make a sprite or image appear on the applet I've asked for help before from my peers and professor, but they don't seem to help. I don't know if I have the image in the wrong location or if my code is bugged, but I would appreciate if someone took a look at it Thanks! Oh! by the way I'm programming in Java and I'm using Eclipse JUNO.
enter code here
package meh;
import java.awt.*;
import javax.swing.JApplet;
import javax.swing.ImageIcon;
public class Draw extends JApplet{
public static void main(String[] args)
{
Draw test = new Draw();
}
private Image exImage;
private boolean imagesLoaded;
public void run()
{
imagesLoaded = false;
try
{
loadImages();
try
{
Thread.sleep(10000);
}
catch(InterruptedException ex){}
}
finally{}
}
public void loadImages()
{
exImage = loadImage("C:/Users/Temp/workspace/From Scratch/bin/Ma_rn_0");
imagesLoaded = true;
repaint();
}
private Image loadImage(String fileName)
{
return new ImageIcon(fileName).getImage();
}
public void paint(Graphics g)
{
if(g instanceof Graphics2D)
{
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
}
if(imagesLoaded)
{
drawImage(g, exImage,0,0, null);
}
else
{
g.drawString("Loading...", 5, 12);
}
}
public void drawImage(Graphics g, Image image, int x, int y, String caption)
{
g.drawImage(image, x, y, null);
g.drawString(caption, x+5, y + 12 +image.getHeight(null));
}
}
Unless they are signed, applets can only load images from the same location from where they originated. Here you are attempting to load an image from the local disk. All initialisation for applet resources should be done from the init method. Images can be loaded as resources from the same JAR file from which they are deployed. You could do
Image exImage = ImageIO.read(getClass().getResourceAsStream("images/MyImage.jpg"))
1 public static void main(String[] args)
Applets are not supposed to have main(), it uses init, start, stop and destroy.
http://docs.oracle.com/javase/tutorial/deployment/applet/getStarted.html
2 Try to learn about EDT concept
3 Don't override paint method
4 Use ImageIO to load images
Related
I observe one thing.
If I performed some of the operations on the bufferImage, like Loading image, drawing some graphics with the help of createGraphics() method,on restoring the same buffer image variable with the same JPEG image it is also showing the drawing performed by me on the previous buffer image.
class Controller {
static Thread second;
static Thread minutes;
static Thread hour;
static Logic l;
static Design d;
static SecondNiddle s;
static MinutNiddle m;
static HourNiddle h;
static BufferedImage img1 ;
Controller(){
Niddle n=new Niddle();
l=new Logic();
s=new SecondNiddle(l);
m=new MinutNiddle(l);
h=new HourNiddle(l);
d=new Design(l,n,s,m,h);
try {
img1 = ImageIO.read(new File("back1.jpg"));
} catch (IOException e) {
}
}
public static void main(String... args) throws Exception{
Controller c=new Controller();
c.myThread();
while(true){
second.start();
second.join();
Temp.setClockBackGround(img1);
minutes.start();
minutes.join();
hour.start();
hour.join();
c.myThread();
}
}
public void myThread(){
second=new Thread(s,"second");
minutes=new Thread(m,"minutes");
hour=new Thread(h,"hour");
}
After performing the second thread operation if I reset the image and perform the following operations in minut thread.
public void run(){
l.minutAngle+=6;
create(Temp.getClockBackGround().createGraphics());
}
public void create(Graphics2D g){
System.out.println(l.minutAngle);
g.setStroke(new BasicStroke(3));
g.drawLine(175,175,getX(115,l.minutAngle),getY(115,l.minutAngle));
g.dispose();
}
the same is happening in the hour thread and getx and logic will provide time and coordinates.Here is the Temp class
import java.awt.*;
import javax.swing.*;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
class Temp{
private static BufferedImage background;
public static void setClockBackGround(BufferedImage bg){
background=bg;
}
public static BufferedImage getClockBackGround(){
BufferedImage b=background;
return b;
}
}
second thread
import java.awt.*;
import javax.swing.*;
import java.awt.image.*;
class SecondNiddle extends JPanel implements Runnable{
public Graphics g;
public Logic l;
BufferedImage bg;
Image img1 = Toolkit.getDefaultToolkit().getImage("yourFile.gif");
SecondNiddle(Logic l){
this.l=l;
setLayout( new BorderLayout() );
setSize(358,380);
img1 = Toolkit.getDefaultToolkit().getImage("back.jpg");
}
public void run(){
for(int i=0;i<60;i++){
try{
Thread.sleep(1000);
}catch(Exception e){}
l.secondAngle+=6;
repaint();
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(Temp.getClockBackGround(),0,0,null);
System.out.println("running the paintComonent...");
g.drawLine(175,175,getX(155,l.secondAngle),getY(155,l.secondAngle));
g.dispose();
}
public int getX(int r,float angle){
return (int)(175+(r*Math.sin(3.1416*angle/180)));
}
public int getY(int r,float angle){
return (int)(175-(r*Math.cos(3.1416*angle/180)));
}
}
and the output is as below
Ok, now I can see what you're trying to do. There are several issues here, but with a change in implementation a number of them will go away.
If you intend to have more than this graphic updating (like if this is part of a game) then you should really create a game loop that does the game logic and then the graphical updates at a fixed rate.
Barring that, if you want a clock background and just move the hands, the best way to do it is to create another empty buffered image with transparency, draw the hands on that, then create a composite of both the background buffered image and the hands buffered image. This requires you only loading the background once, and then reusing it for every update. Psuedo code:
public void init()
{
...
BufferedImage background = ImageIO.read();
BufferedImage foreground = new BufferedImage(background.width,
background.height, BufferedImage.TYPE_ARGB);
BufferedImage composite = new BufferedImage(background.width,
background.height, BufferedImage.TYPE_ARGB);
....
}
....
public void paint()
{
...
Gragphics2d g = (Graphics2d)composite.createGraphics();
g2d.setComposite(
AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0));
g.drawImage(background,0,0,null);
g.drawImage(foreground,0,0,null);
...
}
Or something along these lines.
I'm trying to animate the sprite in my game when a button is pressed, but when I press the button, it skips the animation. Its supposed to go one pixel, change sprites, and then go one more pixel and change back. Here is the code
//for all
import java.nio.file.*;
import javax.imageio.ImageIO;
import java.io.IOException;
import java.awt.image.*;
import java.net.*;
import java.awt.*;
import javax.swing.*;
import static java.lang.invoke.MethodHandles.*;
import java.awt.event.*;
//my Mario class (cut down a lot)
class Mario {
// all numbers multiplied by 2 from OG game
protected Direction dir;
protected int x, y;
protected BufferedImage sprite;
protected String currentSpriteName;
public Mario() {
this.x = 54;
this.y = 808;
dir = Direction.RIGHT;
setSprite(MVCE.SMALLSTANDFACERIGHT);
currentSpriteName = MVCE.SMALLSTANDFACERIGHT;
}
public void moveRight(){
if(this.dir == Direction.LEFT){
this.dir = Direction.RIGHT;
}
else if(this.dir == Direction.RIGHT){
this.x+=1;
}
}
public void animateMoveRight(){
if (currentSpriteName.equals(MVCE.SMALLSTANDFACERIGHT)){
setSprite(MVCE.SMALLWALKFACERIGHT);
}
else if (currentSpriteName.equals(MVCE.SMALLWALKFACERIGHT)){
setSprite(MVCE.SMALLSTANDFACERIGHT);
}
}
public void jump() {
this.y -= 46;
}
public void setSprite(String spriteName) {
URL spriteAtLoc = MVCE.urlGenerator(spriteName);
this.sprite = MVCE.generateAndFilter(sprite, spriteAtLoc);
}
public void getSprite(){
System.out.println(this.currentSpriteName);
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(sprite, 0, 0, null); // DO NOT SET x and y TO ANYTHING,
// this sets 0,0 to top left!!
}
}
// my MarioRender class:
class MarioRender extends JLabel {
protected Mario marioSprite;
public MarioRender() {
marioSprite = new Mario();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
marioSprite.paint(g2);
setBounds(marioSprite.x, marioSprite.y, marioSprite.sprite.getWidth(), marioSprite.sprite.getHeight());
}
public void moveMarioRight(){
marioSprite.moveRight();
marioSprite.animateMoveRight();
setLocation(this.marioSprite.getX(), this.marioSprite.getY());
repaint();
//this is my attempt to make it animate
marioSprite.moveRight();
marioSprite.animateMoveRight();
setLocation(this.marioSprite.getX(), this.marioSprite.getY());
repaint();
}
public void jumpMario() {
marioSprite.jump();
setLocation(this.marioSprite.x, this.marioSprite.y);
repaint();
}
}
// direction class, solely for moving
enum Direction {
LEFT, RIGHT
}
// my calling class, which I called MVCE where I make the frame
public class MVCE extends JFrame {
MarioRender m = new MarioRender();
JLabel bg;
public MVCE() {
bg = new JLabel();
this.setSize(868, 915);
this.setVisible(true);
this.add(bg, BorderLayout.CENTER);
bg.setLayout(null);
bg.add(m);
m.setBounds(m.marioSprite.x, m.marioSprite.y, m.marioSprite.sprite.getWidth(),
m.marioSprite.sprite.getHeight());
KeyListener kl = new MoveListener();
this.addKeyListener(kl);
this.setFocusable(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static final String SMALLSTANDFACERIGHT = "SmallStandFaceRight.bmp"; // 30
// x
// 32
public static final String SMALLJUMPFACERIGHT = "SmallJumpFaceRight.bmp"; // 32
// x
// 32
// generate URL
public static URL urlGenerator(String name) {
URL u = lookup().lookupClass().getResource(name);
return u;
}
// return image with filtered color
public static BufferedImage generateAndFilter(BufferedImage b, URL u) {
try {
b = ImageIO.read(u);
int width = b.getWidth();
int height = b.getHeight();
int[] pixels = new int[width * height];
b.getRGB(0, 0, width, height, pixels, 0, width);
for (int i = 0; i < pixels.length; i++) {
// System.out.println(pixels[i]);
if (pixels[i] == 0xFFff00fe) {
pixels[i] = 0x00ff00fe;
}
}
BufferedImage newSprite = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
newSprite.setRGB(0, 0, width, height, pixels, 0, width);
b = newSprite;
} catch (IOException e) {
System.out.println("sprite not found");
e.printStackTrace();
}
return b;
}
// key listener
class MoveListener implements KeyListener {
public void keyPressed(KeyEvent k) {
if ((k.getKeyCode() == 39)) {
m.moveMarioRight();
///THIS IS SUPPOSED TO MOVE HIM 1, change sprite, and automatically move him back, it moves 2 pixels but no animation
}
if (k.getKeyCode() == 83) { // S key
m.marioSprite.setSprite(SMALLJUMPFACERIGHT);
m.jumpMario();
}
}
public void keyReleased(KeyEvent k) {
}
public void keyTyped(KeyEvent k) {
}
}
public static void main(String[] args) {
MVCE m = new MVCE();
}
}
I tried putting this between the calls to marioMoveRight():
try {
Thread.sleep(200);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
but it just delays the whole thing. I had also tried using an ActionListener, but I don't know how to make it react only when the key is pushed. as I had it,
I had this class inside of MVCE:
class TickListener implements ActionListener{
public void actionPerformed(ActionEvent a){
m.marioSprite.setSprite(Constants.SMALLWALKFACERIGHT);
repaint();
}
}
and this at the end of the MVCE constructor:
ActionListener ac = new TickListener();
final int DELAY = 1000;
Timer t = new Timer(DELAY, ac);
t.start();
but then, the Mario just moves automatically. I do not want to use a sprite sheet for this project, I am trying to do it as this guy did for SMB1.
Many problems, don't know which one or if any will fix the problem:
Don't use a KeyListener. If a component doesn't have focus the component won't receive the event. Instead use Key Bindings.
Don't use "==" to compare Objects. Instead you should be using the equals(...) method.
Don't override paintComponent. A painting method is for painting only. You should not be changing the bounds of the component in the painting method.
Do basic debugging (problem solving) before asking a question. A simple System.out.println(...) added to various methods will determine if the code is executing as you expect. Then when you ask a question you can ask a specific question telling us which block of code does not execute as you expect.
You never actually call the method animateMoveRight(), and if I understand correcly, that's what's changing the sprite. Also, I doubt that you see the sprite change when calling the same method twice in a row without any delay.
Try putting the animateMoveRight() method into the moveRight() or the moveMarioRight() method and, if neccessary because the animation is too fast, add your delay code back where you had it. Be careful not to let the main thread sleep, as this causes everything to freeze, so start another one or use a timer etc.
EDIT: Good timers
I'm not too familiar with the Timer class, so I end up using the Thread variant. There are many tutorials for that out there, just search for "java threads" or "java multithreading". This is IMO a solid tutorial you can check out.
I am creating a lightweight client for the game Runescape that has various user features such as custom keybinds/hotkeys. I'm pretty good with java and swing, but AWT and applets I am mediocre at best. I was able to get the applet downloaded and displayed on a JPanel and then in a JFrame and the game runs perfectly so far. However, when adding features I ran into a problem when I tried to implement a screenshot function to the client.
It's hard to post a concise working example so I'll post the methods I was trying based off of some other SO answers I was reading. I tried creating BufferedImage from the Applet, applet Canvas, the JPanel it is handled by, and the JFrame.
Here are some things I tried to create a screenshot from the Applet canvas:
public BufferedImage getScreenShot() {
//getting the applet canvas
Canvas canvas = (Canvas) this.getApplet().getComponent(0);
//bufferedImage to draw to
BufferedImage image = new BufferedImage(canvas.getWidth(), canvas.getHeight(), BufferedImage.TYPE_INT_ARGB);
//Graphics2D g2=(Graphics2D)image.getGraphics();
//test.print(g2);
//g2.dispose();
Graphics g = image.getGraphics();
Image image2 = canvas.createImage(canvas.getWidth(), canvas.getHeight());
canvas.print(g);
System.out.println("Canvas Size: " + canvas.getSize().width + " x " + canvas.getSize().height);
return image;
}
This one I tried in the JPanel class which holds only the Applet:
public BufferedImage getScreenShotFINAL(){
BufferedImage bi = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
applet.paint(bi.createGraphics());
return bi;
}
I understand that the idea here is to create an off-screen BufferedImage, then to create a Graphics2d object and to then call the applet's paint() method to paint to the off-screen image. I tried this solution from here:
public BufferedImage getScreenShotFINAL2() {
Dimension size = applet.getSize();
BufferedImage offScreenImage = (BufferedImage) applet.createImage(size.width, size.height);
Graphics2D g2 = offScreenImage.createGraphics();
g2.setBackground(applet.getBackground());
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.clearRect(0, 0, size.width, size.height);
applet.paint(g2);
return offScreenImage;
}
When saving the BufferedImages these and other methods I tried to a file the images just show up as black, just the default background color. Is there a good way to just get a BufferedImage from the JPanel which would include the Applet so I never have to deal with the Applet directly? Another thing, I had to override the java Canvas class in order to get the game to display (because it is double buffered I believe). I tried following a bunch of solutions from here but had no success. Any suggestions would be greatly appreciated. I also can provide a link to the full project or the custom Canvas project if you would like. Thanks!
EDIT
Here is the Canvas class which overrides the java AWT one. Didn't write it, followed a tutorial for this one and I think this is where the problem is, because the paint() method only calls clearRect():
package java.awt;
import Client.Client;
import java.awt.image.BufferStrategy;
import java.awt.peer.CanvasPeer;
import javax.accessibility.*;
import loaders.ClientPool;
public class Canvas extends Component implements Accessible {
private Client client = null;
private static final String base = "canvas";
private static int nameCounter = 0;
private static final long serialVersionUID = -2284879212465893870L;
public Canvas() {
super();
}
public Canvas(GraphicsConfiguration config) {
this();
setGraphicsConfiguration(config);
}
#Override
void setGraphicsConfiguration(GraphicsConfiguration gc) {
synchronized(getTreeLock()) {
CanvasPeer peer = (CanvasPeer)getPeer();
if (peer != null) {
gc = peer.getAppropriateGraphicsConfiguration(gc);
}
super.setGraphicsConfiguration(gc);
}
}
#Override
public Graphics getGraphics(){
if (this.client == null) {
this.client = ClientPool.getClient(this);
}
if (client != null) {
//call custom draw functions for specific client. for drawing/double buffering
return client.drawGraphics((Graphics2D) super.getGraphics());
}
return super.getGraphics();
}
#Override
String constructComponentName() {
synchronized (Canvas.class) {
return base + nameCounter++;
}
}
#Override
public void addNotify() {
synchronized (getTreeLock()) {
if (peer == null)
peer = getToolkit().createCanvas(this);
super.addNotify();
}
}
#Override
public void paint(Graphics g) {
g.clearRect(0, 0, width, height);
}
#Override
public void update(Graphics g) {
g.clearRect(0, 0, width, height);
super.paint(g);
}
#Override
boolean postsOldMouseEvents() {
return true;
}
#Override
public void createBufferStrategy(int numBuffers) {
super.createBufferStrategy(numBuffers);
}
#Override
public void createBufferStrategy(int numBuffers,
BufferCapabilities caps) throws AWTException {
super.createBufferStrategy(numBuffers, caps);
}
#Override
public BufferStrategy getBufferStrategy() {
return super.getBufferStrategy();
}
#Override
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessibleAWTCanvas();
}
return accessibleContext;
}
protected class AccessibleAWTCanvas extends AccessibleAWTComponent
{
private static final long serialVersionUID = -6325592262103146699L;
public AccessibleRole getAccessibleRole() {
return AccessibleRole.CANVAS;
}
}
}
I'm trying to show some images on my applet and have them move around but whenever I run my project through the applet all I get is a blank/black screen. I can change the color of the background, but I can't see any of my images. Also, the applet isn't initialized when I try to start the applet. Here's the code:
package test;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.net.URL;
public class MCTaRE extends Applet implements Runnable, KeyListener {
private Character character;
private Image image, robot;
private Graphics graphics;
private URL base;
#Override
public void init() {
setSize(800, 480);
setBackground(Color.BLACK);
setFocusable(true);
Frame frame = (Frame) this.getParent().getParent();
frame.setTitle("Test");
robot = getImage(base, "data/character.png");
}
#Override
public void start() {
Thread thread = new Thread(this);
thread.start();
character = new Character();
}
#Override
public void stop() {
}
#Override
public void run() {
while (true) {
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public void update(Graphics g) {
if (image == null) {
image = createImage(this.getWidth(), this.getHeight());
graphics = image.getGraphics();
}
// graphics.setColor(getBackground());
graphics.fillRect(0, 0, getWidth(), getHeight());
// graphics.setColor(getForeground());
paint(graphics);
g.drawImage(image, 0, 0, this);
}
#Override
public void paint(Graphics g) {
g.drawImage(robot, character.getInitX() - 61,
character.getInitY() - 63, this);
}
public void KeyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_SPACE:
System.out.println("Space");
break;
}
}
public void KeyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
}
package test;
public class Character {
private int initX = 100;
private int initY;
private int speedX = 0;
public void update(){
//if (key listener is at the top){
moveLeft();
//}
//else {
stop();
//}
initY = 200;
}
public int getInitX() {
return initX;
}
public int getInitY() {
return initY;
}
public int getSpeedX() {
return speedX;
}
public void setInitX(int initX) {
this.initX = initX;
}
public void setInitY(int initY) {
this.initY = initY;
}
public void setSpeedX(int speedX) {
this.speedX = speedX;
}
public void moveLeft(){
speedX = -5;
}
public void stop(){
speedX = 0;
}
}
Any help would be greatly appreciated I need to make this work. I can try to use an AVD but I think that would complicate things even more. And a JApplet isn't an option.
"but I can't see any of my images."
You have a few options loading the images.
I like to use getClass().getResource("/path/to/image") as it load from the class path, which is used from embedded resources.
try {
robot = ImageIO.read(getClass().getResource("/data/character.png"));
} catch (IOException ex) {
ex. printStackTrace();
}
You could do the same thing using ImageIcon.getImage where you can avoid the try/catch but I prefer the former, so you can get exception if path is incorrect
robot = new ImageIcon(getClass().getResource("/data/character.png")).getImage();
For Applet, you can use getCodeBase() as seen here
try {
URL url = new URL(getCodeBase(), "data/character.png");
robot = ImageIO.read(url);
} catch (IOException e) {
e.printStackTrace();
}
NOTE: All three options will work with your code (just tested all), given your file structure is as follows, with data in the src
ProjectRoot
src
data
character.png
test
MCTaRE.java
Side Note
You are not calling super.paint in your paint method, which will leave you with paint artifacts. So call it
#Override
public void paint(Graphics g) {
super.paint(g);
Why code an Applet in the first place. If it must be an Applet, why AWT Applet and not Swing JApplet. If this is a class assignment, have your professor read Why CS teachers should stop teaching Java applets
If you want to ditch the zero (AWT) and get with the hero (Swing), read more at Creating GUI with Swing
I have a quick question about Java. I'm sorry if this question is really basic, but I'm a beginner Java programmer :D
I want to render a 2d image in a window, but I can't figure it out. I've looked at the graphics API here:
http://download.oracle.com/javase/1.4.2/docs/api/java/awt/Graphics.html
and the only method I could find that might work is drawImage().
It wasn't working for me, though, but maybe it has to do with the ImageObserver Observer parameter? I just put null for that following some tutorial I found somewhere, but I still get a compile error:
Here is my paint method:
public void paint(Graphics g)
{
Image img1 = Toolkit.getDefaultToolkit().getImage("theImage.png");
g.drawImage(img1, 100, 100, null);
} // public void paint(Graphics g)
and here are the methods that call it:
public static void main(String[] args)
{
MyGame game = new MyGame();
game.setVisible(true);
game.play();
} // public static void main(String[] args)
/** The play method is where the main game loop resides.
*/
public void play()
{
boolean playing = true;
//Graphics g = new Graphics();
while (playing)
{
paint();
}
} // public void play()
The thing is when I call paint in the while loop, I get this error:
paints(java.awt.Graphics) in MyGame cannot be applied to ()
What does that mean? How can I fix it so I can successfully render a 2d image?
Thanks in advance :D
Instead of paint(); use repaint();
You should be overriding paintComponent(Graphics g). Also, as #TotalFrickinRockstarFromMars suggested, you should be invoking repaint().
You overrid the paintComponent(Graphics g)
class Game extends JComponent { // Your game class
Image img = null;
public Game() {
img = getImage("/theImage.png");
}
private Image getImage(String imageUrl) {
try {
return ImageIO.read(getClass().getResource(imageUrl));
} catch (IOException exp) {}
return null;
}
paintComponent(Graphics g) {
g.drawImage(img, 100, 100, null);
}
}