Abbildungsmatrix für Isometrie

Neue Frage »

Auf diesen Beitrag antworten »
Tommy1234 Abbildungsmatrix für Isometrie

Hallo,

ich habe ein aus 3x3 Feldern bestehendes isometrisches Spielfeld (Kachelgröße:128x64) auf den Bildschirm gezeichnet und möchte nun mit der Maus auslesen können, auf welche Kachel (z.B. 1,2) ich geklickt habe.

Hier ist zunächst einmal der Code:

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
public void loadLevel(){
for(int x = 0;x<mapWidth;x++){
			for(int y = 0;y<mapHeight;y++){
				int mapx = (x+y)*64;
				int mapy = (x-y)*32+64;
				p[x][y] = new Point(mapx,mapy);
			}
		}
	}


 
Auf diesen Beitrag antworten »
Tommy1234

Wurde beim schreiben gestört.... .

Also mapx bzw. mapy bestehen aus x-y bzw. x+y.
Das kann man als Matrix sehen in der Form

1 -1
1 1.

Nun ist ja die Abbildungsmatrix A*s + v = x;

Wobei A die o.g. Matrix ist, s ist (64,32) und v ist die Translation hier: (128,0).

Wenn man mapx bzw. mapy umformt kommt man auf den Kachelindex:

tilex = (mapx/64 + mapy/32)/2;
tiley = (mapy/32 - mapx/64)/2;

Das geteilt durch zwei kommt zustande wenn man mit geraden Werten rechnen will, denn die Matrix liefert 0.5. Also mal 2.

Wie im Code oben habe ich mapx bzw. mapy durch mousex bzw. mousey ersetzt.

Aber, wenn man die Applikation dann startet und testet stimmt das Ergebnis nur teilweise, denn es wird nur an bestimmten Punkten in einer Kachel korrekt angezeigt je nachdem wo man halt auf die Kachel klickt und in derselben Kachel auch falsch.

D.h. ich lieg nicht so ganz falsch aber ich finde den mathematischen Fehler nicht. Braucht man noch sowas wie eine Translationsmatrix oder geht das völlig anders?

Sorry wegen dem ersten unpräzisen post.

Gruß Tommy
Auf diesen Beitrag antworten »
eulerscheZahl

Ehrlich gesagt verstehe ich immer noch nicht, was genau du machst.
Könntest du zumindest so viel Code anhängen, dass ich dein Programm ausführen und testen kann?
Auf diesen Beitrag antworten »
Tommy1234

Hier der Code:


Game Klasse:

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
package main;

import java.awt.*;
import java.awt.image.*;

import javax.swing.JFrame;

public class Game extends Canvas implements Runnable{

	private static final long serialVersionUID = 1L;
	
	private final int WIDTH = 320;
	private final int HEIGHT = 160;
	private final int SCALE = 3;
	
	private Thread thread;
	private JFrame frame;
    private Mouse mouse;
    private boolean running = false;
    
    private Level level;
    
	public Game() {
		
		Dimension size = new Dimension(WIDTH*SCALE,HEIGHT*SCALE);
		setPreferredSize(size);
		
		frame = new JFrame();
		level = new Level(3,3);
		mouse = new Mouse();
		addMouseListener(mouse);
	}
	
	public synchronized void start(){
		running = true;
        thread = new Thread(this,"Display");
        thread.start();
    }
	
	public synchronized void stop(){
		running = false;
        try {
			thread.join();
		} catch (InterruptedException e) {e.printStackTrace();}
    }
    
    public void run() {
        
    	long lastTime = System.nanoTime();
    	long timer = System.currentTimeMillis();
        final double ns = 1000000000.0 / 60.0;
        double delta = 0;
        int updates = 0;
        int frames = 0;
        while(running){
            long now = System.nanoTime();
            delta += (now - lastTime) / ns;
            lastTime = now;
            while(delta>=1){
                update();
                updates++;
                delta--;
            }
            render();
            frames++;
        
            if(System.currentTimeMillis()-timer>1000){
                timer+=1000;
                frame.setTitle("UPS:   " + updates + "   FPS:   " + frames);
                frames = 0;
                updates = 0;
            }
        }
        stop();
    }
    
	public void update(){
		
		level.update();
    }
    
    public void render(){
    	
    	BufferStrategy bs = getBufferStrategy();
        if(bs == null){
            this.createBufferStrategy(3);
            return;
        }
        
        Graphics g = bs.getDrawGraphics();
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, getWidth(), getHeight());
        level.render(g);
        g.dispose();
        bs.show();
    }
    
    public static void main(String[] args) {
		
		Game game = new Game();
		game.setFocusable(true);
		game.requestFocus();
		game.frame.add(game);
		game.frame.pack();
		game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		game.frame.setLocationRelativeTo(null);
		game.frame.setVisible(true);
		
		game.start();

	}
}CODE]

Dann die Level Klasse:

[CODE]package main;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;

public class Level {

	private int mapWidth;
	private int mapHeight;
	
	private int tilex;
	private int tiley;
	
	private Point[][] p;
	
	
	public Level(int mapWidth,int mapHeight) {
		this.mapWidth = mapWidth;
		this.mapHeight = mapHeight;
		p = new Point[mapWidth][mapHeight];
		loadLevel();
	}
	
	public void loadLevel(){
		for(int x = 0;x<mapWidth;x++){
			for(int y = 0;y<mapHeight;y++){
				int mapx = (x-y)*64+128;
				int mapy = (x+y)*32;
				p[x][y] = new Point(mapx,mapy);
			}
		}
	}
	
	public void update(){
		
		tilex = (((Mouse.mousex)/64+((Mouse.mousey)/32))/2);
		tiley = ((((Mouse.mousey)/32-(Mouse.mousex)/64))/2);
		System.out.println(" x   "+tilex + "  y  " + tiley);
		
	}
	
	public void render(Graphics g){
		for(int x = 0;x<mapWidth;x++){
			for(int y = 0;y<mapHeight;y++){
				//int mapx = (x-y)*32;
				//int mapy = (x+y)*16;
				//g.drawImage(gras, mapx, mapy, null);
				
				g.setColor(Color.BLACK);
				g.drawLine(p[x][y].x,p[x][y].y+32,p[x][y].x+64,p[x][y].y);
				g.drawLine(p[x][y].x+64,p[x][y].y,p[x][y].x+128,p[x][y].y+32);
				g.drawLine(p[x][y].x+128,p[x][y].y+32,p[x][y].x+64,p[x][y].y+64);
				g.drawLine(p[x][y].x+64,p[x][y].y+64,p[x][y].x,p[x][y].y+32);
			}
		}
	}

}


Und noch die Maus:

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
package main;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class Mouse extends MouseAdapter{

	public static int mousex,mousey;
	
	public void mouseClicked(MouseEvent e) {
		
		mousex = e.getX();
		mousey = e.getY();
	}
}


Ok das sollte laufen.
 
Auf diesen Beitrag antworten »
eulerscheZahl

Jetzt verstehe ich erst, wie dein Spielfeld aussieht.
code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
public void update() {
	double px = Mouse.mousex;
	double py = Mouse.mousey;
	double dx = (32.0 / 64.0 * px - py + 32 * mapHeight) / (2 * 32.0 / 64.0);
	double dy = -(-32.0 / 64.0 * px - py + 32 * mapHeight) / (4 * 32.0 / 64.0);

	tilex = (int) dx / 64;
	tiley = (int) dy / 32;
	System.out.println("mx = " + Mouse.mousex + "  my = " + Mouse.mousey + "  x = " + tilex + "  y = " + tiley + "  dx = " + dx + "  dy = " + dy);
}
Auf diesen Beitrag antworten »
Tommy1234

Noch ne Frage :

Wie bekomme ich jetzt den Ursprung nach oben also in P(192/0), so das die Kachel oben in der Mitte 0,0 ist????
Auf diesen Beitrag antworten »
eulerscheZahl

Die faule Lösung: x-Achse nachträglich umdrehen.
code:
1:
tilex = mapHeight - 1 - (int) dx / 64;
Auf diesen Beitrag antworten »
Tommy1234

Danke!!
Auf diesen Beitrag antworten »
Tommy1234

Sorry muss nochmal altes Thema aufgreifen.

Der Punkt(0,0) liegt bei mir auf x + 200.
Aber trotz Drehung wird's Seitenverkehrt angezeigt.
Ansonsten geht's.
Kein Plan warum???
Auf diesen Beitrag antworten »
Tommy1234

Ok, dieses Thema hat sich fast erledigt, denn....

Das mit dem richtigen Tile anklicken habe ich jetzt geschafft: Jetzt versuche ich eine Einheit auf dem isometrischen Grid zu markieren.
Das Grid ist 200x200 groß, die Einheit steht auf Position 0,50 auf dem Grid und wird mittels isometrischer Umrechnung darauf platziert. Um die Einheit herum habe ich ein Rechteck gezeichnet mit iso-Einheit-x bzw. y und möchte nun abfragen, ob mein Mauszeiger(Klick) im Rechteck liegt, wenn ja wird markiert, andernfalls nicht.

Doch es will irgendwie nicht.

Vielleicht kann mir jemand helfen.

Hier Code + Screenshot(dort wo der Mauszeiger ist klicke ich hin):

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
if(unit!=null){
			int isox = (boundingBox.y - boundingBox.x)*2;
			int isoy = (boundingBox.x + boundingBox.y)*1;
			Rectangle box = new Rectangle(isox,isoy,width,height);
			if(MouseInput.left && box.contains(tilex,tiley)){
				marked = true;
				
			}
			System.out.println(box.x+"   "+MouseInput.mousex);
			g.setColor(Color.RED);
			g.drawRect(box.x,box.y,width,height);
			if(MouseInput.left && !box.contains(tilex,tiley)){
				marked = false;
			}
			if(marked){
				g.setColor(Color.GREEN);
				g.fillRect(box.x,box.y,width,5);
			}
			
			plot(unit,width,height,figure,isox-16+400,isoy-16,g);
		}
	} 
 
Neue Frage »
Antworten »


Verwandte Themen