Hello for a school exercise i need to create a game and i decided to create Pacman. Everything goes well but one thing i can't accomplish is to draw a pacman dude and his ghosts.. i made and oval but what now? i want the pacman mouth also to open and close as it moves. can someone help drawing this?
below what i have till now:
package h04PacMan;
import java.awt.*;
public class DrawPacMan {
public void drawPacMan(Graphics g, int x, int y, Color color) {
g.setColor(color); // set color
g.fillOval(x, y, 50, 50); // paint
g.setColor(Color.black);
g.drawOval(x, y, 50, 50); // outline
// mouth?
}
public void drawGhost(Graphics g, int x, int y, Color color) {
g.setColor(color); // color
// here goes shape
}
}
Instead of using drawOval and fillOval, you should have a look at drawArc and fillArc.
See java.awt.Graphics.
Concerning the animation of the mouth: Given that pacman is constantly moving, you could combine pacman's position with a sine function to get a nice and smooth mouth movement, something like this:
angle = 20 * (Math.sin((x + y)*2*Math.PI/50) + 1); # alt. betw. 0 and 40
g.fillArc(x, y, 50, 50, angle/2, 360-angle);
This way, Pacman's mouth will automatically do one open-close-cycle as he moves a distance of his own size through the maze. (You may have to tweak the numbers a bit to fit your setup.)
Of course, you will still need a thread to run the game as a whole, but the animation of Pacman's mouth can be done this way, too, without extra threads.
So there are a couple of things going on here that you will need to address.
1. Drawing Characters
I'll only address drawing Pacman here.
Thinking about the Pacman game, Pacman's character has two states -- mouth closed, and mouth opened (in each cardinal direction!). This will be important for when we animate Pacman in a moment, so first, lets establish our pacman shape by using the fillArc method from the Graphics library.
Example of Mouth-Open Pacman:
g.setColor(Color.yellow);
g.fillArc(0,0,150,150,30,300);
This will create pacman in the top-left corner of your window, with pacman's mouth facing to the right of the screen. The last two paramters of the fillArc method control this opening -- the 5th parameter is the starting angle, and the sixth parameter is the angle of the full arc. You may infer from this that the start angle 0 is the horizontal line going from the center of the arc to the right of the screen. Also remember from mathematics that a full circle is 360 degrees.
Using this information, try drawing mouth-opened Pacman facing up, down and left. After you do that, fill the entire arc to draw Pacman with his mouth closed. Also consider other methods in the Graphics library you can use to draw your ghosts!
2. Animating Pacman
For this task you will probably want to implement some sort of Thread structure to animate Pacman, which gets quite a bit more complicated than what you've demonstrated here. Since we don't know your program specifications, and you also haven't demonstrated any code relating to the animation yet, I'm hesitant to lay this out any further. However, I will direct you to some links on the matter:
For a general overview, check out Java Tutorials - Concurrency.
If you're using Swing for this project, you may want to use SwingWorker for your threads.
I'd recommend taking advantage Area/Path2D API.
Have a look at Graphics 2D
You can have a look at the sample code in this answer for an example
Related
I'm currently working on an Arduino Uno and Processing interface with the idea of revealing an image much like a "scratch off lottery ticket." I currently have the image uploaded into the sketch and the black background ready, however I'm not sure at this point how to start revealing the image through fill()
I know that I could technically use an ellipse of 1 pixel wide that will SLOWLY reveal the image (and subsequently take forever because the Arduino joystick isn't very cooperative.) but I was hoping there would be an easier way to reveal it. Does anyone have any ideas?
Here is the code:
void draw() {
noStroke();
ellipse(xPos, yPos, 1,1);
if(zButton == 0){
background(0);
}
color c = img.get(xPos, yPos);
fill(c);
serialEvent(myPort);
}
This is the draw function, it reads the joystick's interface through the serialEvent function, as of right now I have a 1x1 ellipse revealing the image pixel by pixel, but that would be extremely tedious
Thanks guys, any help is appreciated
Instead of using .get(x,y) to get individual pixels, you can use loadPixels to expose the pixel array, and simply color those instead. This is generally much faster than using the get and set functions.
To speed things up further, cache the image's pixels and track which consecutive lines you can just copy over (for instance, if you offer a 5 pixel radius ellipse, then you can track the fact that you need to copy 5 pixels starting at position X, which you can then copy over as a single call. The more the user scratches, the more pixels you can copy that way in a single call)
I have an assignment to draw a certain number of circles using java.awt.Graphics.
Drawing the circles is fairly simple, but I am only supposed to draw the circle if it appears within the visible area. I know I can call method getClipBounds() to determine the drawing area, but I'm having trouble finding a java implementation of a way to determine if a circle intersects a Rectangle.
Is that the right way to go about determining if the circle I want to draw will be completely visible or is there a simpler way?
Don't use the Graphics.fillOval(...) method to do the painting.
Instead you can use the Graphics2D.fill(Shape) method. You can create oval Shape objects using the Ellipse2D class.
but I'm having trouble finding a java implementation of a way to determine if a circle intersects a Rectangle.
The Shape object has a method that will allow you to get the rectangular bounds of the Shape. Then you can use the Rectangle.contains(...) method of the your Graphics area to determine if the Shape is fully contained within your panel.
Check out Playing With Shapes for more information and ideas.
use Ellipse2D.Float to instanciate an object for example:
Shape circle = new Ellipse2D.Float(100.0f, 100.0f, 100.0f, 100.0f);
basically the parameters,from left to right, are: Height, Width, X of the Top left and Y of the top left, and by keeping the X and Y both greater or equal to zero, your circle will always be visible.
the parameters of the Float(...) are documented for the Ellipse2D.Float in Java SE 7 in
http://docs.oracle.com/javase/7/docs/api/java/awt/geom/Ellipse2D.Float.html
I have a space with bouncing balls, and when i drag mouse I want a line to be drawn in it so that balls start bouncing from it as well.
I can draw a line consisting of small circles, and add their inside area together, and if a ball intersects this area change direction. This works. The problem is that circles don't produce solid line (as mouseDragged events are fired too rarely), but if I use Line2D instead, it doesn't enclose any area.
In every mouse dragged event I can interpolate data between startPoint and endPoint and draw a circle at obtained x,y. It works, but everything freezes terribly
I can check if ball's covering rectangle contains certain color (and if so, change direction), but again how should it be done -- checking every pixel doesn't seem efficient at all?
Is there a way/best way to deal with it?
but if I use Line2D instead, it doesn't enclose any area.
Use a Path2D or a Polygon that has a (very thin) width. It will look like a line, but have an area.
Then use it in the code seen in this answer.
I have been searching for a introductory to 2D selection in OpenGL ES in Stack Overflow. I mostly see questions about 3D.
I'm designing a 2D tile-based level editor on Android 4.0.3, using OpenGL ES. In the level editor, there is a 2D, yellow, square object placed in the center of the screen. All I wanted is to detect to see if the object has been touched by a user.
In the level editor, there aren't any tiles overlapping. Instead, they are placed side-by-side, just like two nearby pixels in a bitmap image in MS Paint. My purpose is to individually detect a touch event for each square object in the level editor.
The object is created with a simple vertex array, and using GL_TRIANGLES to draw 2 flat right triangles. There are no manipulations and no loading from a file or anything. The only thing I know is that if a user touches any one of the yellow triangles, then both yellow triangles are to be selected.
Could anyone provide a hint as to how I need to do this? Thanks in advance.
EDIT:
This is the draw() function:
public void draw(GL10 gl) {
gl.glPushMatrix();
gl.glTranslatef(-(deltaX - translateX), (deltaY - translateY), 1f);
gl.glColor4f(1f, 1f, 0f, 1f);
//TODO: Move ClientState and MatrixStack outside of draw().
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertices);
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 6);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glPopMatrix();
}
EDIT 2:
I'm still missing some info. Are you using a camera? or pushing other
matrixes before the model rendering?. For example, if you are using an
orthographic camera, you can easily unproject your screen coordinates
[x_screen, y_screen] like this (y is analogous):
I'm not using a camera, but I'm probably using an orthographic projection. Again, I do not know, as I'm just using a common OpenGL function. I do pushing and popping matrices, because I plan on integrating many tiles (square 2D objects) with different translation matrices. No two tiles will have the same translation matrix M.
Is a perspective projection the same as orthographic projection when it comes to 2D? I do not see any differences between the two.
Here's the initial setup when the surface is created (a class extending GLSurfaceView, and implementing GLSurfaceView.Renderer):
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
}
public void onSurfaceCreated(GL10 gl, EGLConfig arg1) {
reset();
}
public void onDrawFrame(GL10 gl) {
clearScreen(gl);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrthof(0f, super.getWidth(), 0f, super.getHeight(), 1, -1);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
canvas.draw(gl);
}
private void clearScreen(GL10 gl) {
gl.glClearColor(0.5f, 1f, 1f, 1f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
}
A basic approach would be the following:
Define a bounding box for each "touchable" object. This could be
just a rectangle (x, y, width, height).
When you update a tile in the world you update its
bounding box (completely in world coordinates).
When user touches the screen, you have to unproject screen
coordinates to world coordinates
Check if unprojected point overlaps with any bounding box.
Some hints on prev items.[Edited]
1 and 2. You should have to keep track of where you are rendering
your tiles. Store their position and size. A rectangle is a
convenient structure. In your example it could be computed like
this. And you have to recompute it when model changes. Lets call it Rectangle r:
r.x = yourTile.position.x -(deltaX - translateX)
r.y = yourTile.position.y -(deltaY - translateY)
r.width= yourTile.width //as there is no model scaling
r.height = yourTile.height//
3 - if you are using
an orthographic camera, you can easily unproject your screen
coordinates [x_screen, y_screen] like this (y is analogous):
x_model = ((x_screen/GL_viewport_width) -0.5 )*camera.WIDTH + Camera.position.x
4 - For each of your Rectangles check if [x_model; y_model] is inside it.
[2nd Edit] By the way you are updating your matrixes, you can consider you are using a camera with postition surfaceView.width()/2, surfaceView.height()/2. You are matching 1 pixel on screen to 1 unit in world, so you dont need to unproject anything. You can replace that values on my formula and get x_screen = x_model - (You 'll need to flip the Y component of the touch event because of the Y grows downwards in Java, and upwards in GL).
Final words. If user touches point [x,y] check if [x, screenHeight-y]* hits some of your rectangles and you are done.
Do some debugging, log the touching points and see if they are as expected. Generate your rectangles and see if they match what you see on screen, then is a matter of checking if a point is inside a rectangle.
I must tell you that you should not set the camera to screen dimensions, because your app will look dramatically different on different devices. This is a topic on its own so i won't go any further, but consider defining your model in terms of world units - independent from screen size. This is getting so off-topic, but i hope you have gotten a good glimpse of what you need to know!
*The flipping i told you.
PS: stick with the orthographic projection (perspective would be more complex to use).
Please, allow me to post a second answer to your question. This is completely more high-level/philosophical. May be a silly, useless answer but, I hope it will help someone new to computer graphics to change it's mind to "graphics mode".
You can't really select a triangle on the screen. That square is not 2 triangles. That square is just a bunch of yellow pixels. OpenGL takes some vertices, connects them, process them and colors some pixels on the screen. At one stage on the graphics pipeline even geometrical information is lost, and you only have isolated pixels. That's analogous to a letter printed by a printer on a paper. You usually don't process information from a paper (ok, maybe a barcode reader does :D)
If you need to further process your drawings, you have to model them and process them yourself with auxiliary data structures. That's why I suggested you created a rectangle to model your tiles. You create your imaginary "world" of objects, and then render them to screen. The user touch-event does not belong to the same world, so you have to "translate" screen coordinates into your world coordinates. Then you change something in your world (may be the user drags her finger and you have to move an object), and back again tell OpenGL to render your world to screen.
You should operate on your model, not the view. Meshes are more of a view thing, so you shouldn't mix them with the model information, it's a good practice to separate both things. (please, an expert correct me, I'm quite a graphics hobbyist)
Have you checked out LibGDX?
Makes life so much easier when working with OpenGL ES.
I have trouble drawing a triangle with the draw(Graphics g) method in Java.
I can draw a rectangle like so:
public void draw(Graphics g) {
g.setColor(colorFill);
g.fillRect(p.x, p.y, width, height);
g.setColor(colorBorder);
g.drawRect(p.x, p.y, width, height);
drawHandles(g);
Where p represents "the top left corner of the shapes". How would I draw the triangle in the same manner?
Could someone give me an example for a standard triangle?
There is not a drawTriangle method neither in Graphics nor Graphics2D. You need to do it by yourself. You can draw three lines using the drawLine method or use one these methods:
drawPolygon(int[] xPoints, int[] yPoints, int nPoints)
drawPolygon(Polygon p)
drawPolyline(int[] xPoints, int[] yPoints, int nPoints)
These methods work with polygons. You may change the prefix draw to fill when you want to fill the polygon defined by the point set. I inserted the documentation links. Take a look to learn how to use them.
There is the GeneralPath class too. It can be used with Graphics2D, which is capable to draw Shapes. Take a look:
http://docs.oracle.com/javase/tutorial/2d/geometry/arbitrary.html
You should try using the Shapes API.
Take a look at JPanel repaint from another class which is all about drawing triangles, look to the getPath method for some ideas
You should also read up on GeneralPath & Drawing Arbitrary Shapes.
This method is much easy to apply AffineTransformations to
Use a line algorithm to connect point A with point C, and in an outer loop, let point A wander towards point B with the same line algorithm and with the wandering coordinates, repeat drawing that line. You can probably also include a z delta with which is also incremented iteratively. For the line algorithm, just calculate two or three slopes for the delta change of each coordinate and set one slope to 1 after changing the two others proportionally so they are below 1. This is very important for drawing closed geometrical areas between connected mesh particles. Take a look at the Qt Elastic Nodes example and now imagine drawing triangles between the nodes after stretching this over a skeleton.
As long as it will remain online
there is no command directly to draw Triangle. For Drawing of triangle we have to use the concept of lines here.
i.e, g.drawLines(Coordinates of points)
There is no direct method to draw a triangle.
You can use drawPolygon() method for this.
It takes three parameters in the following form:
drawPolygon(int x[],int y[], int number_of_points);
To draw a triangle:
(Specify the x coordinates in array x and y coordinates in array y and number of points which will be equal to the elements of both the arrays.Like in triangle you will have 3 x coordinates and 3 y coordinates which means you have 3 points in total.)
Suppose you want to draw the triangle using the following points:(100,50),(70,100),(130,100)
Do the following inside public void paint(Graphics g):
int x[]={100,70,130};
int y[]={50,100,100};
g.drawPolygon(x,y,3);
Similarly you can draw any shape using as many points as you want.
You can use Processing library:
https://processing.org/reference/PGraphics.html
There is a method called triangle():
g.triangle(x1,y1,x2,y2,x3,y3)