I
Idiat
Gast
Hallo zusammen,
beim Anzeigen eines Tilesets in einem FullScreen und beim darstellen einer Spielfigur
tritt bei mir das Problem auf, dass sich die Spielfigur nur sehr unflüssig bewegt.
Nach längerem suchen fiel mir dann auf, dass die getSubImage()-Methode für dieses Problem sorgt.
Mein Vorgehen: Ich schneide mit Hilfe des Codes unten 32x32 große Bilder aus einem großten Tileset aus und lade diese in eine ArrayList (tiles).
(selber Code ist auch im unteren vorhanden)
Wenn ich die Bilder einzeln in die ArrayList lade und anzeige geht das ganze problemlos,
sobald ich auch nur ein Image mit getSubImage clippe geht es nicht mehr und es muss ja
wohl eine Möglichkeit geben dies über getSubImage zu machen statt die Grafiken
alle einzeln zu laden.
Woran liegt das ganze?
Außerdem fiel mir auf, dass es beim Bewegen der Grafik zur Anschlagverzögerung von Windows
kommt, wenn man eine Taste gedrückt hält. Sprich: Die Grafik bewegt sich erst einmal
und dann nach längerem Halten durchgehend. Wie kann ich das ganze umgehen ohne
die Verzögerung in Windows herunterzusetzen? Schließlich hab ich das Problem in anderen
2D-Spielen auch nicht.
Hier der gesamte Code, hoffe er ist nicht zu lang.
Main.java
ScreenManager.java
Beim OOP kam es bis jetzt oft zu Fehlern, deswegen gehe ich hier gerade sparsam mit mehreren Klassen um. Wird aber dann noch geändert, sobald sich die Figur mal flüssig bewegt, ich bitte also
um Verständnis und hoffe der Code ist auch so lesbar.
Viele Grüße,
Idiat
beim Anzeigen eines Tilesets in einem FullScreen und beim darstellen einer Spielfigur
tritt bei mir das Problem auf, dass sich die Spielfigur nur sehr unflüssig bewegt.
Nach längerem suchen fiel mir dann auf, dass die getSubImage()-Methode für dieses Problem sorgt.
Mein Vorgehen: Ich schneide mit Hilfe des Codes unten 32x32 große Bilder aus einem großten Tileset aus und lade diese in eine ArrayList (tiles).
Java:
int width=picTileset.getWidth()/32;
int height=picTileset.getHeight()/32;
for(int x=0;x<width;x++){
for(int y=0;y<height;y++){
tile = picTileset.getSubimage(x*32, y*32, 32, 32);
this.tiles.add(tile);
}
}
Wenn ich die Bilder einzeln in die ArrayList lade und anzeige geht das ganze problemlos,
sobald ich auch nur ein Image mit getSubImage clippe geht es nicht mehr und es muss ja
wohl eine Möglichkeit geben dies über getSubImage zu machen statt die Grafiken
alle einzeln zu laden.
Woran liegt das ganze?
Außerdem fiel mir auf, dass es beim Bewegen der Grafik zur Anschlagverzögerung von Windows
kommt, wenn man eine Taste gedrückt hält. Sprich: Die Grafik bewegt sich erst einmal
und dann nach längerem Halten durchgehend. Wie kann ich das ganze umgehen ohne
die Verzögerung in Windows herunterzusetzen? Schließlich hab ich das Problem in anderen
2D-Spielen auch nicht.
Hier der gesamte Code, hoffe er ist nicht zu lang.
Main.java
Java:
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.*;
public class Main implements KeyListener {
private static DisplayMode modes[] = {
new DisplayMode(800, 600, 32,0),
new DisplayMode(800, 600, 24,0),
new DisplayMode(800, 600, 16,0),
new DisplayMode(640, 480, 32,0),
new DisplayMode(640, 480, 24,0),
new DisplayMode(640, 480, 16,0),
};
private boolean running;
protected ScreenManager s;
//tile engine
ArrayList<BufferedImage> tiles = new ArrayList<BufferedImage>();
public Image face;
public BufferedImage tile;
public BufferedImage test;
int map_width = 32;
int map_height = 24;
int[][][] map = new int[map_width][map_height][3];
int sx = 32;
int sy = 32;
String mess = "";
public static void main(String[] args){
Main c = new Main();
c.run();
}
//stop method
public void stop() {
running = false;
}
//call init and gameloop
public void run() {
try{
init();
loadImages();
loadMap();
gameLoop();
}finally{
s.restoreScreen();
}
}
//set to full screen
public void init() {
s = new ScreenManager();
DisplayMode dm = s.findFirstCompatibleMode(modes);
s.setFullScreen(dm);
Window w = s.getFullScreenWindow();
w.setFocusTraversalKeysEnabled(false);
w.addKeyListener(this);
w.setFont(new Font("Arial", Font.PLAIN, 20));
w.setBackground(Color.BLACK);
w.setForeground(Color.WHITE);
running = true;
mess = "press escape to exit";
}
//load images
public void loadImages(){
try {
BufferedImage picTileset=ImageIO.read(new File("gfx/Tileset2.png"));
int width=picTileset.getWidth()/32;
int height=picTileset.getHeight()/32;
for(int x=0;x<width;x++){
for(int y=0;y<height;y++){
tile = picTileset.getSubimage(x*32, y*32, 32, 32);
this.tiles.add(tile);
}
}
}catch (IOException error){
System.err.println("gfx not found");
error.printStackTrace();
}
face = new ImageIcon("gfx/face.png").getImage();
}
public void loadMap(){
try {
BufferedInputStream buf=new BufferedInputStream(new FileInputStream("D:\\test.test"));
ObjectInputStream read = new ObjectInputStream(buf);
map=(int[][][]) read.readObject();
String name=(String) read.readObject();
String fileName=(String) read.readObject();
read.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
}
}
//main gameLoop
public void gameLoop() {
long startTime = System.currentTimeMillis();
long cumTime = startTime;
while(running){
long timePassed = System.currentTimeMillis() - cumTime;
cumTime += timePassed;
update(timePassed);
Graphics2D g = s.getGraphics();
draw(g);
g.dispose();
s.update();
try{
Thread.sleep(20);
}catch(Exception ex){}
}
}
//keyPressed
public void keyPressed(KeyEvent ke){
int keyCode = ke.getKeyCode();
if(keyCode == KeyEvent.VK_ESCAPE){
stop();
}else if(keyCode== KeyEvent.VK_F1){
}else{
mess = "Pressed : "+KeyEvent.getKeyText(keyCode);
ke.consume();
}
switch (ke.getKeyCode()) {
case KeyEvent.VK_RIGHT: {
sx+=2;
}
break;
case KeyEvent.VK_LEFT: {
sx-=2;
}
break;
case KeyEvent.VK_DOWN: {
sy+=2;
}
break;
case KeyEvent.VK_UP: {
sy-=2;
}
break;
}
}
//keyReleased
public void keyReleased(KeyEvent e){
int keyCode = e.getKeyCode();
mess = "Released : "+KeyEvent.getKeyText(keyCode);
e.consume();
}
//last method from interface
public void keyTyped(KeyEvent e){
e.consume();
}
//update animation
public void update(long timePassed){
}
//draws to screen
public void draw(Graphics2D g){
Window w = s.getFullScreenWindow();
g.setColor(w.getBackground());
g.fillRect(0, 0, s.getWidth(), s.getHeight());
g.setColor(w.getForeground());
for(int x=0;x < map.length;x++){
for(int y=0;y < map[0].length;y++){
for(int z=0; z<=0; z++){
if(map[x][y][z] != 0){
g.drawImage(tiles.get(0), x*32, y*32, null);
}
}
}
}
g.drawImage(face, sx, sy, null);
g.drawString(mess, 30, 30);
}
}
ScreenManager.java
Java:
import java.awt.*;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
public class ScreenManager {
private GraphicsDevice vc;
// give vc access to monitor screen
public ScreenManager() {
GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment();
vc = e.getDefaultScreenDevice();
}
//get all compatible DM
public DisplayMode[] getCompatibleDisplayModes() {
return vc.getDisplayModes();
}
//compares DM passed in vc DM and see if they match
public DisplayMode findFirstCompatibleMode(DisplayMode modes[]) {
DisplayMode goodModes[] = vc.getDisplayModes();
for(int x=0; x<modes.length; x++) {
for(int y=0; y<goodModes.length;y++) {
if(displayModesMatch(modes[x],goodModes[y])) {
return modes[x];
}
}
}
return null;
}
//get current DM
public DisplayMode getCurrentDisplayMode() {
return vc.getDisplayMode();
}
//checks if two modes match each other
public boolean displayModesMatch(DisplayMode m1, DisplayMode m2) {
if(m1.getWidth() != m2.getWidth() || m1.getHeight() != m2.getHeight()){
return false;
}
if(m1.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI && m2.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI && m1.getBitDepth() != m2.getBitDepth()){
return false;
}
if(m1.getRefreshRate() != DisplayMode.REFRESH_RATE_UNKNOWN && m2.getRefreshRate() != DisplayMode.REFRESH_RATE_UNKNOWN && m1.getRefreshRate() != m2.getRefreshRate()){
return false;
}
return true;
}
//make frame full screen
public void setFullScreen(DisplayMode dm) {
JFrame f = new JFrame();
f.setUndecorated(true);
f.setIgnoreRepaint(true);
f.setResizable(false);
vc.setFullScreenWindow(f);
if(dm != null && vc.isDisplayChangeSupported()){
try{
vc.setDisplayMode(dm);
}catch(Exception ex){}
}
f.createBufferStrategy(2);
}
//set graphics object = to this
public Graphics2D getGraphics(){
Window w = vc.getFullScreenWindow();
if(w != null){
BufferStrategy s = w.getBufferStrategy();
return (Graphics2D)s.getDrawGraphics();
}else{
return null;
}
}
//updates display
public void update(){
Window w = vc.getFullScreenWindow();
if(w != null){
BufferStrategy s = w.getBufferStrategy();
if(!s.contentsLost()){
s.show();
}
}
}
public Window getFullScreenWindow(){
return vc.getFullScreenWindow();
}
//get width of window
public int getWidth(){
Window w = vc.getFullScreenWindow();
if(w != null){
return w.getWidth();
}else{
return 0;
}
}
//get height of window
public int getHeight(){
Window w = vc.getFullScreenWindow();
if(w != null){
return w.getHeight();
}else{
return 0;
}
}
//get out of full screen
public void restoreScreen(){
Window w = vc.getFullScreenWindow();
if(w != null){
w.dispose();
}
}
//create image compatible with monitor
public BufferedImage createCompatibleImage(int w, int h, int t){
Window win = getFullScreenWindow();
if(win != null){
GraphicsConfiguration gc = win.getGraphicsConfiguration();
return gc.createCompatibleImage(w,h,t);
}
return null;
}
}
Beim OOP kam es bis jetzt oft zu Fehlern, deswegen gehe ich hier gerade sparsam mit mehreren Klassen um. Wird aber dann noch geändert, sobald sich die Figur mal flüssig bewegt, ich bitte also
um Verständnis und hoffe der Code ist auch so lesbar.
Viele Grüße,
Idiat