Hello, I have a sprite sheet, were every 32x32 height wise is a different sprite. Wdith wise is each frame of animation. How do I only get a 32x32 block from the big sprite sheet?
Use this drawImage method.
It allows you to specify a subpart of an image to be drawn on a specified place on another image.
On a side note, it’s common to load and chop up the tilesets in small images when the game, level or something similar is initialized and then just paint the choped pics.
I think it’s actually most efficient to draw using that method and not chop the image up. Better for considering switching to OpenGL as well. That’s the best way to go in that context also
Any image larger than 256x256 isn’t accelerated behind the scenes (via automatic/volatile images), so on a practical note you’ll need to have sub images in order to get good drawing speed.
Last time I tried it, using individual images was somewhat faster than drawing a sub image (even when the master image was less than 256x256).
Don’t guess - profile!
how do you chop up peices of an image and store them as separate images anyway?
[quote]Use this drawImage method.
It allows you to specify a subpart of an image to be drawn on a specified place on another image.
On a side note, it’s common to load and chop up the tilesets in small images when the game, level or something similar is initialized and then just paint the choped pics.
[/quote]
Okay thankyou! Now, I made a function to make the ground, which draws a bunch of 32x32 grass tiles over the ground. then after that, it draws the character sprite. now I’ve coded it so every game loop, it moves right.(x++;) Now, that character sprite flickers, but the ground doesn’t. Every loop it draws a 1000 tiles over a 800x600 area. then after it does that, it draws the character sprite, and then refreshes the screen for buffer. but the character sprite flickers but not the ground tiles. could it be because of drawing all the tiles slows it down?
Also, is there a way to draw an image iunto a createImage() variable?
Also can you explain that drawImage code you posted. And is it true I can only have a heightxwidth of 256
[quote]could it be because of drawing all the tiles slows it down?
[/quote]
you do use bufferstrategy and the sprite IS drawn every tick? then I have no idea what might be wrong
uh… what? do you mean into an imageproducer? o_O
[quote]Also can you explain that drawImage code you posted.
[/quote]
how about reading the docs…?
[quote]And is it true I can only have a heightxwidth of 256
[/quote]
noone ever said that. sprites above 256x256 are just not accelerated (so you should not use them. you may, though)
Sorry for the long time no reply. I got the code working perfectly, now I wish to fix the flickering issue…
Heres my Update()
public void update(Graphics g){
player.drawAvatar(sprites,player_x,player_y,sprite,dir,g);
//create buffer
if(buffer == null){
buffer = createImage(app_width,app_height);
bgraphics = buffer.getGraphics();
}
repaint();
bgraphics.setColor(getBackground());
bgraphics.fillRect(0,0,app_width,app_height);
repaint();
//Draw Gui
gui.drawGUI(g,gui1,gui2);
gui.drawStats(g,25,20,1025,5);
gui.drawMenu(g);
bgraphics.setColor(getForeground());
repaint();
player.drawAvatar(sprites,player_x,player_y,sprite,dir,g);
//Draws the appropiate menu that the user clicked
switch(menu_item){
case 0:
//do nothing
break;
case 1:
gui.drawInventory(g);
repaint();
break;
case 2:
gui.drawEquipment(g);
break;
case 3:
gui.drawMagic(g);
break;
case 4:
gui.drawMStats(g);
break;
case 5:
gui.drawOptions(g);
break;
}
//re-draw map + character
for(y = 0; y < 480; y = y + 32){
g.drawString("Cirdan",player_x-5,player_y - 15);
makeRow(0,y,g);
player.drawAvatar(sprites,player_x,player_y,sprite,dir,g);
repaint();
}
}
public void paint(Graphics g){
repaint();
}
and heres my game loop…
while(true){
repaint();
if(walk == true){
walk = false;
} else if(walk = false) {
walk = true;
}
//-----------------------------------------
//Checks to see if the user exits the room - BLOCK OF CODE = TEMPORARY
//WILL BE USED TO TELEPORT FROM ONE MAP TO ANOTHER
//-----------------------------------------
if(player_y + 32 > 480){
player_y = 0;
repaint();
}
if(player_y < 0) {
player_y = 448;
repaint();
}
if(player_x < 0){
player_x = 640 - 32;
repaint();
}
if(player_x + 32 > 640){
player_x = 0;
repaint();
}
//-----------------------------------------
try{
th.sleep(20);
} catch(InterruptedException ex){
}
What class is that update(Graphics g) method in? What does it inherit from? You could be overriding the real update() method. If so, calling repaint() from inside it probably isn’t healthy.
Kev
Okay, I changed my code. Every thing is drawin in the paint() and the buffer clears the screen throguh the update() But, my gui code won’t draw throguh the paint() I get this exception. But if I draw my gui in the update() method, it works, but the text flickers. Any idea?
my draw gui code…
public void drawGUI(Graphics g,Image gui1,Image gui2){
g.drawImage(gui1,640,0,this);
g.drawImage(gui2,0,480,this);
//Draw Stats
}
public void drawStats(Graphics g,int hp,int mp,int xp,int level){
//Set font Color
g.setColor(Color.white);
//Draw the infomation
g.drawString("HP: " + hp,650,100);
g.drawString("MP: " + mp,650,115);
g.drawString("Experience: " + xp,650,130);
g.drawString("Level: " + level,650,145);
}
public void drawInventory(Graphics g){
// y =187
g.drawString("Inventory",685,200);
}
public void drawMagic(Graphics g){
// y = 187
g.drawString("Magic",700,200);
}
public void drawOptions(Graphics g){
g.drawString("Options",695,200);
}
public void drawEquipment(Graphics g){
g.drawString("Equipment",685,200);
}
public void drawMStats(Graphics g){
g.drawString("Stats",700,200);
}
public void drawMenu(Graphics g){
//y = 437
g.drawString("Menu",700,450);
g.drawString("Inventory",650,465);
g.drawString("Equipment",650,480);
g.drawString("Magic",650,495);
g.drawString("Stats",650,510);
g.drawString("Options",650,525);
}
Maybe if you post the exception you’re getting?
Kev
And the two lines mentioned, which are they, since we don’t have any lines numbers in the code above?
Kev
line 311 and 312 =
which is in update()
bgraphics.setColor(getBackground());
bgraphics.fillRect(0,0,640,480);
Then on line 248:
which is in my game loop
247 try{
248
249 th.sleep(20);
my current update()
public void update(Graphics g){
//create buffer
if(buffer == null){
buffer = createImage(app_width,app_height);
bgraphics = buffer.getGraphics();
}
//draw gui
gui.drawGUI(g,gui1,gui2);
gui.drawStats(g,25,20,1025,5);
gui.drawMenu(g);
//Draws the appropiate menu that the user clicked
switch(menu_item){
case 0:
//do nothing
break;
case 1:
gui.drawInventory(g);
repaint();
break;
case 2:
gui.drawEquipment(g);
break;
case 3:
gui.drawMagic(g);
break;
case 4:
gui.drawMStats(g);
break;
case 5:
gui.drawOptions(g);
break;
}
bgraphics.setColor(getBackground());
bgraphics.fillRect(0,0,640,480);
paint(bgraphics);
g.drawImage(buffer,0,0,this);
my current game loop…
while(true){
repaint();
//-----------------------------------------
//Checks to see if the user exits the room - BLOCK OF CODE = TEMPORARY
//WILL BE USED TO TELEPORT FROM ONE MAP TO ANOTHER
//-----------------------------------------
if(player_y + 32 > 480){
player_y = 0;
repaint();
}
if(player_y < 0) {
player_y = 448;
repaint();
}
if(player_x < 0){
player_x = 640 - 32;
repaint();
}
if(player_x + 32 > 640){
player_x = 0;
repaint();
}
//-----------------------------------------
try{
th.sleep(20);
} catch(InterruptedException ex){
}
Acording to your exceptions, 312 should be where you call updateGUI(). The other line number was 322? Have you been changing the code while reporting the problems?
If possible it might be easier if you post the code as a whole. Null pointers probably just mean paint() is getting called before you’ve had a chance to create your buffer.
Kev
ok, heres my code…
import javax.swing.*;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.*;
import java.awt.image.*;
import java.io.*;
import java.net.*;
public class SecretsofCelebrindal extends JApplet implements KeyListener,MouseListener,Runnable {
//-----------------------------------------
//Variables
//-----------------------------------------
int app_width,app_height,tiles_y,tiles_x,map_x,map_y,y,x,i,tiles,player_x,player_y, menu_item,dir,sprite;
public boolean map_created,walk,walking;
Graphics bgraphics;
player player;
gui gui;
Image grass,sprites,gui1,gui2,buffer,map;
String name,command;
char key;
public Thread th;
static int keyUp = 38;
static int keyDown = 40;
static int keyLeft = 37;
static int keyRight = 39;
//-----------------------------------------
//Misc. Functions
//-----------------------------------------
//-----------------------------------------
//For the map, draw a row - TEMPORARY
public void makeRow(int mx,int my,Graphics g){
for(mx = 0; mx< 640; mx = mx + 32){
g.drawImage(grass,mx,my,this);
tiles++;
if(mx == 800){
map_created = true;
break;
}
}
}
//-----------------------------------------
//Checks if a menu item has been clickd
public boolean socButton(int y,MouseEvent m){
boolean clicked;
if(m.getX() > 650 && m.getX() < 700 && m.getY() > y && m.getY() < y+15){
clicked = true;
} else {
clicked = false;
}
return clicked;
}
//-----------------------------------------
//For futer browser functionality
public String getAppletInfo() {
//You can replace this with your own message, but leave SOC Source Written by Ryan Capote
return "Secrets of Celebrindal V1.0 Written by Ryan Capote. SOC Source V 1.0 Written by Ryan Capote.";
}
//-----------------------------------------
//A small function to load the images. Help keeps the code clean
public void loadImages(){
//load the images
grass = getImage(getCodeBase(),"gfx/grass.GIF");
sprites = getImage(getCodeBase(),"gfx/Sprites.GIF");
gui1 = getImage(getCodeBase(),"gfx/gui1.gif");
gui2 = getImage(getCodeBase(),"gfx/gui2.gif");
}
//-----------------------------------------
//Initialization
//-----------------------------------------
public void init() {
//do variable stuff
app_width = 640;
app_height = 480;
tiles_x = 0;
tiles_y = 0;
map_x = 32;
map_y = 32;
player_y = 64;
player_x = 64;
addKeyListener(this);
addMouseListener(this);
walk = true;
walking = false;
sprite = 198;
}
//-----------------------------------------
//When the game starts
//-----------------------------------------
public void start() {
//create player
player = new player();
//create GUI
gui = new gui();
//Load images
loadImages();
th = new Thread(this);
th.start();
}
//------------------------------------------
//Controles
//------------------------------------------
public void keyPressed(KeyEvent e){
walking = true;
//Check arrows for character movement - TO BE UPDATED - NEEDS ANIMATION
if(e.getKeyCode() == keyUp){
player_y = player_y - 3;
walk = true;
dir = 1;
repaint();
} else if (e.getKeyCode() == keyDown){
player_y = player_y + 3;
walk = true;
dir = 2;
repaint();
} else if (e.getKeyCode() == keyLeft){
player_x = player_x - 3;
dir = 3;
walk = true;
repaint();
} else if (e.getKeyCode() == keyRight){
player_x = player_x + 3;
dir = 4;
walk = true;
repaint();
}
}
public void keyReleased(KeyEvent e){
if(e.getKeyCode() == keyUp){
walk = false;
} else if (e.getKeyCode() == keyDown){
walk = false;
} else if (e.getKeyCode() == keyLeft){
walk = false;
} else if (e.getKeyCode() == keyRight){
walk = false;
}
}
public void keyTyped(KeyEvent e){
// key = e.getKeyChar();
// command = command + key;
}
public void mouseClicked(MouseEvent m){
//Inventory
if(socButton(455,m) == true){
menu_item = 1;
}
//Equipment
if(socButton(470,m) == true){
menu_item = 2;
}
//Magic
if(socButton(485,m) == true){
menu_item = 3;
}
//Stats
if(socButton(500,m) == true){
menu_item = 4;
}
//Options
if(socButton(515,m) == true){
menu_item = 5;
}
}
public void mousePressed(MouseEvent m){ }
public void mouseReleased(MouseEvent m){ }
public void mouseEntered(MouseEvent m){ }
public void mouseExited(MouseEvent m) { }
//-----------------------------------------
//game loop
//-----------------------------------------
public void run(){
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
while(true){
repaint();
//-----------------------------------------
//Checks to see if the user exits the room - BLOCK OF CODE = TEMPORARY
//WILL BE USED TO TELEPORT FROM ONE MAP TO ANOTHER
//-----------------------------------------
if(player_y + 32 > 480){
player_y = 0;
repaint();
}
if(player_y < 0) {
player_y = 448;
repaint();
}
if(player_x < 0){
player_x = 640 - 32;
repaint();
}
if(player_x + 32 > 640){
player_x = 0;
repaint();
}
//-----------------------------------------
try{
th.sleep(20);
} catch(InterruptedException ex){
}
}
}
//-----------------------------------------
//Buffer, to stop flickering
//------------------------------------------
public void update(Graphics g){
//create buffer
if(buffer == null){
buffer = createImage(app_width,app_height);
bgraphics = buffer.getGraphics();
}
bgraphics.setColor(getBackground());
bgraphics.fillRect(0,0,640,480);
//draw gui
gui.drawGUI(g,gui1,gui2);
gui.drawStats(g,25,20,1025,5);
gui.drawMenu(g);
//Draws the appropiate menu that the user clicked
switch(menu_item){
case 0:
//do nothing
break;
case 1:
gui.drawInventory(g);
repaint();
break;
case 2:
gui.drawEquipment(g);
break;
case 3:
gui.drawMagic(g);
break;
case 4:
gui.drawMStats(g);
break;
case 5:
gui.drawOptions(g);
break;
}
paint(bgraphics);
g.drawImage(buffer,0,0,this);
}
//Draw the Screen
public void paint(Graphics g){
//re-draw map + character
for(y = 0; y < 480; y = y + 32){
bgraphics.drawString("Cirdan",player_x-5,player_y - 15);
makeRow(0,y,g);
player.drawAvatar(sprites,player_x,player_y,sprite,dir,g);
}
}
//------------------------------------------
//ending
//------------------------------------------
public void stop(){
}
public void destroy() {
}
}
Only exception I got was:
java.lang.NullPointerException
at SecretsofCelebrindal.paint(SecretsofCelebrindal.java:322)
Line number probably doesn’t match up because I had to mod the code to run it locally. Fixed by updating your paint() method to:
public void paint(Graphics g){
if (bgraphics == null) {
System.out.println("Buffer not enabled yet");
return;
}
//re-draw map + character
for(y = 0; y < 480; y = y + 32){
bgraphics.drawString("Cirdan",player_x-5,player_y - 15);
makeRow(0,y,g);
}
The paint() method can get called by the AWT event system directly. In this case it gets called before your update() is called and hence the code failed because the “bgraphics” hadn’t been initialised yet.
It all ran (once i replaced your gfx references, and pasted in the GUI methods from the last post) swimingly.
Kev
Okay, what I did was put the part were it creates the buffer in the paint method, now I don’t have the exception anymore.But the gui still doesn’t want to work through paint() wich makes it flicker a lot. But drawing the map and the character in the paint() method, flixed that flickering.
I think thats because you’re not passing the buffer’s graphics context into the drawGUI methods, rather you’re passing the real graphics context from the paint() method.
Kev
PArden my noobness but, what does that mean? lol