I've tried searching around, but nothing really seems to cover what I'm looking for.
I'm currently making a mini graphics editor for my course, and its working okay at the minute for the paintbrush tool, only that it doesn't seem to work very well at all if I'm moving the mouse too quickly.
The drawing is done through a mouse listener, triggering a 'draw' event while the mouse is held down. It then adds a circle (size and color based upon settings elsewhere) each time the loop rolls. The method takes the initial mouse location (MouseEvent e), and then uses a PointerInfo to update the current mouse position with some calculations around it to make sure it draws in the current place (the canvas uses a null layout).
Some code to show what It's doing:
void setMouseDown(MouseEvent e){
PointerInfo mousePos = MouseInfo.getPointerInfo();
int mouseRelativeX = e.getX();
int mouseRelativeY = e.getY();
int startX = (int) mousePos.getLocation().getX();
int startY = (int) mousePos.getLocation().getY();
while(mouseDown){
mousePos = MouseInfo.getPointerInfo();
mouseMarginX = mouseRelativeX - (startX - (int) mousePos.getLocation().getX());
mouseMarginY = mouseRelativeY - (startY -(int) mousePos.getLocation().getY());
if(curTool == "drawPen"){
DrawPen drawPen = new DrawPen(toolSize, Color.BLACK);
add(drawPen);
drawPen.setBounds(mouseMarginX, mouseMarginY, toolSize, toolSize);
}else if(curTool == ""){
}else if(curTool == ""){
}else if(curTool == ""){
}
revalidate();
repaint();
}
}
If anybody has any advice on the best way to do this, then it'd be much appreciated. Thanks
Related
I'm trying to zoom a grid in Processing and I am having trouble with applying the correct translation such that zooming is centered around the mouse position. I have searched the web for a while but nothing I try seems to work.
The screen size is width and height and the mouse position is mouseX and mouseY.
The code I have at the moment is below, but it zooms the grid (controlled by player.zoom) from the top left corner which is not what I want. To update the translation of the grid, player has the 2d vector player.translate.
void mouseWheel(MouseEvent event) {
float zoomFactor = 200.0f;
float scroll = event.getCount();
player.zoom -= scroll * player.zoom / zoomFactor;
// player.translate.x += something;
// player.translate.y += something;
}
If you need more details to answer I can link the repo with the source code.
I have created a very simple mock-up for you which will hopefully point you in the right direction into applying this to your player.
So this little demo shows the zooming in to the centre of an ellipse whilst keeping it as the central focus.
float scale = 1;
// displacement left/right
float xPan = 720;
// displacement up/down
float yPan = 450;
boolean zoomIn = true;
void setup() {
size(1440, 900);
}
void draw() {
// allows us to zoom into the center of the screen rather than the corner
translate(width/2, height/2);
scale(scale);
translate(-xPan, -yPan);
background(200);
// draws the ellipse in the center
ellipse(width/2, height/2, 100, 100);
// does the zooming
if (zoomIn) {
scale *= 1.01;
}
}
I suggest you to copy this into a new project and then comment out specific lines to try to understand what's going on and how you can transfer this over to your own project.
The same principles still apply, I didn't do this with mouse input in the effort of making the program as simple as possible.
there's a problem drawing or Setting size of a JPanel when i drag the mouse,
the location i setted where i click and the size depending of the drag position(X and Y) drawing a resizable rectangle(JPanel).
private void panelMouseDragged(java.awt.event.MouseEvent evt) {
rSX = (int)MouseInfo.getPointerInfo().getLocation().getX();
rSY = (int)MouseInfo.getPointerInfo().getLocation().getY();
rectanguloDefault.setBounds(rX,rY,rSX-rX,rSY-rY);
}
private void panelMousePressed(java.awt.event.MouseEvent evt) {
rX = (int)MouseInfo.getPointerInfo().getLocation().getX();
rY = (int)MouseInfo.getPointerInfo().getLocation().getY();
rectanguloDefault.setLocation(rX,rY);
}
but when i drag mouse in a negative coordinate of the click(Start of drawing) it disappear.
here a better explain
http://i.picasion.com/resize80/49c88c55d4c11c53c020acfcc4fc2f45.png
but when i drag mouse in a negative coordinate
rectanguloDefault.setBounds(rX,rY,rSX-rX,rSY-rY);
Your width/height calculation always assumes you drag the mouse in a positive direction.
You need to use the absolute value of the two points:
int width = Math.abs(rSX - rX);
int height = Math.abs(rSY - rY);
rectanguloDefault.setBounds(rX, rY, width, height);
Your x/y values will also need to be the minimum of (rX and rSX) and (ry and rSY). You can use the Math.min(...) method for this.
I'm creating a simple FPS game where the camera movement is controlled with the mouse. It's fairly simple to move the camera with the mouse when it's inside the window. But how can I make this work even when I'm OUT of the window?
I've heard some thing about fixing the mouse in the center of the screen, but I'm not sure how to get this to work.
I currently have the following:
public void mouseMoved(MouseEvent event) {
x = X;
y = Y;
X = event.getX();
Y = event.getY();
}
public void update() {
dX = X - x;
dY = Y - y;
x = X;
y = Y;
}
I've heard some thing about fixing the mouse in the center of the screen, but I'm not sure how to get this to work.
That is a very common way to do it. After you have checked how much your mouse has moved and used that information for camera movement, just move the cursor back to screen center.
Consider something like this:
Vec2 mouseDelta = getMousePosition();
camera.CalculateMovement(mouseDelta);
setMousePosition(0, 0);
You need to "capture" the mouse in your window, typically on the mouse down ( don't forget to release it ).
onMouseDown()
{
BeginCapture();
}
...
ReleaseCapture();
I'm trying to create a simple Android game, a 2D action shooter which has 2 control sticks (circles) on the screen, the left one is movement control and the right one weapon control. Direction is being controlled by the position of your thumb relative to the circle’s center.
I've been following a tutorial on this site: http://www.kilobolt.com/day-7-creating-an-android-game-from-start-to-finish.html but it only gave me the base to work on. I have no programming experience so I'm quite lost now.
I got the movement working only on TOUCH_DOWN event, the hero moves to about where it should but to change direction I have to lift my thumb and touch the circle again. TOUCH_DRAGGED (or ACTION_MOVE) is broken because if I drag my finger across the circle the character moves really fast. I guess the problem is too many touch events are being handled, but I have no idea how to fix it.
How can I change this so that I can drag my thumb around the circle and the hero will change its direction instantly, and keep its speed constant all the time? Also the speed should be the same no matter how close or far from the center of the circle you touch.
private void updateRunning(List<TouchEvent> touchEvents, float deltaTime) {
int len = touchEvents.size();
for (int i = 0; i < len; i++) {
TouchEvent event = touchEvents.get(i);
if (event.type == TouchEvent.TOUCH_DOWN || event.type == TouchEvent.TOUCH_DRAGGED) {
if (inBounds(event, 50, 300, 150, 150, 'c')) {
ctrl.setX(event.x);
ctrl.setY(event.y);
ctrl.direction();
hero.move(ctrl.getDirX(), ctrl.getDirY());
}
}
if (event.type == TouchEvent.TOUCH_UP) {
if (inBounds(event, 0, 0, 35, 35,'r')) {
pause();
}
hero.stopMove();
}
}
hero.update();
The movement: hero's speedX and speedY are added to hero's centerX and centerY on every hero.update() call.
public void move(float x, float y) {
speedX += x * MOVESPEED;
speedY += y * MOVESPEED;
}
This method that handles the x & y speed. Found it here at stackoverflow, and because touch_down event is working ok, I guess it's doing it's job. Although I feel it's not exactly how it's supposed to be. L_STICK_C is a constant with values of 100 and 350 (center of the circle).
public void direction() {
dir.x = x - L_STICK_C.x;
dir.y = y - L_STICK_C.y;
double hyp = Math.sqrt(dir.x * dir.x + dir.y * dir.y);
dir.x = (float) (dir.x / hyp);
dir.y = (float) (dir.y / hyp);
}
I suggest you look into some game programming tutorials. You usually would not move the character directly from the touch input. You'd set a game state variable once a game loop which would correspond to the position of your thumb inputs. Then you'd only update the hero once per game loop based on those inputs. This lets allows you to keep the game input control code, and hero code separate, and makes it re-usable for other parts of your game.
EDIT:
Based on your code, every time you drag your finger, you generate a bunch of dragged events. So you are adding onto your characters speed for each event. You should probably just be looking at the distance to center and x / y of the input on the last touch event, not all of them.
I'm trying to rotate the camera around an object by using the touchscreen. The rotation around Y axis works fine (The X axis is disabled). Rotation around the X axis is really weird. when the Object (its a rocket) gets higher rocket.position().y++ & scene.camera().position.y++, the rotation around the x axis gets bigger and weird. If the rockets stops rocket.position().y = 500; & scene.camera().position.y = 500;, I can't rotate around x axis, I zoom in or out the object instead. With both axis enabled its weird as hell.
In initScene I set the camera to look at the center of the rocket.
Here's my code:
initScene:
scene.camera().position.z = 90;
scene.camera().target = raketeOBJ.position();
onTouchEvent:
public boolean onTouchEvent(MotionEvent me) {
if (me.getAction() == MotionEvent.ACTION_DOWN) {
xpos = me.getX();
ypos = me.getY();
return true;
}
if (me.getAction() == MotionEvent.ACTION_UP) {
xpos = -1;
ypos = -1;
touchTurn = 0;
touchTurnUp = 0;
return true;
}
if (me.getAction() == MotionEvent.ACTION_MOVE) {
float xd = me.getX() - xpos;
float yd = me.getY() - ypos;
xpos = me.getX();
ypos = me.getY();
touchTurn = xd / -200f;
touchTurnUp = yd / -200f;
return true;
}
try {
Thread.sleep(15);
} catch (Exception e) {
}
return super.onTouchEvent(me);
}
UpdateScene:
if (touchTurn != 0) {
scene.camera().position.rotateY(touchTurn);
touchTurn = 0;
}
if (touchTurnUp != 0) {
scene.camera().position.rotateX(touchTurnUp);
touchTurnUp = 0;
}
I think it is a view-orientation-issue. try basic android opengl example "rotating cubes", i think it is a similar behaviour.
To avoid this you have to transform display-coordinates into min3D object rotation-coordinates.
Think about moving your finger 1cm on display to the left, with 3D-object following your finger. This means x_display = x_object.
If you rotate your object, there is still a fixed connection between display and object.
(x_display = - 1cm) equals (x_object = -1cm)
at 90° & 270° your object will move xy-inverted, at 180° your object will move x-inverted.
use some sin/cos to overcome this.
edit: also rotationangle (object) = - rotationangle (camera)
One option is to rotate the container itself instead of the camera. In min3d you often work with an Object3dContainer as a class variable in your activity that displays the model. When you get your MotionEvent you can use the method rotation() from your Object3dContainer class and set x or y properties as appropriate.
You keep saying wierd, but you know that it doesn't describe what you see. Rotate is actually method of Number3d. It doesn't know about the target, so I guess rotation is done according the center, not according the rocket (Didn't quite check that, just a guess). There might be 2 solutions:
The easiest thing is to set the rocket to (0,0,0) and instead moving the rocket, move evertything else. Well that would be a stupid suggestion. Forget it.
The other solution is to calculate camera rotation traectory using sin() and cos()
There might be a third solution, but I didn't think a a lot about it and it might be wrong. What you have to do is move the camera like target is at (0,0,0), rotate and then return the camera.
Would look like something like this:
Number3d target = scene.camera.target;
Number3d cp = scene.camera.position.clone();
// move position like target is (0,0,0)
cp.x -= target.x;
cp.y -= target.y;
cp.z -= target.z;
cp.roateX(angle);
// restore offset
cp.x += target.x;
cp.y += target.y;
cp.z += target.z;
scene.camera.position.setAllFrom(cp);
You can try 3 but don't rely it'll do the job.