Im trying to make a game in java. My problem is that I dont have a initialized method or when I try to create one, my repaint() method substitute my initialized method. I need an initialized to generate my map. Because my map is a list of polygons and I want to set the background when clicked. So, if it is generating every time in a loop called by repaint() I cant do that.
My code:
Run Method:
#Override
public void run()
{
while (isRunning)
{
backPanel.repaint();
}
}
My backpanel class
int jogadas = 1;
Paint method:
#Override
public void paint(Graphics canvasOriginal)
{
super.paint(canvasOriginal);
canvas = (Graphics2D) canvasOriginal;
canvas.setColor(Color.BLACK);
mapa = new Mapa(canvas);
mapa.DrawMapa(100, 50, 5);
getJogada();
}
int getVez() {
if(jogadas % 2 == 0) {
return 1;
}
return 0;
}
void getJogada() {
Hexagono hex = mapa.selecionarHex(x, y);
if(!hex.getPrenchido()) {
if(jogador1.getNumero() == getVez()) {
hex.Preencher(jogador1.getColor());
} else {
hex.Preencher(jogador2.getColor());
}
jogadas++;
}
}
Obs: the mapa.selectHex selects the hex in a list. The hex.preencher() fill the hex polygon.
Result:
Related
In my application, I made an array to control the flag images in my output. This worked fine but when I remove an element from my array the picture doesn't change at all.
class Flag{
Image FlagImage;
int FlagNum = 0;
public Flag(int FlagNum) {
this.FlagNum = FlagNum;
try{
FlagImage = ImageIO.read(new File("flag1.png"));
}catch(Exception e){
}
}
public void Update() {
}
public void Draw(Graphics g) {
//Draw Flag
g.drawImage(FlagImage, ((FlagNum) % 3+1) * 100-100, (int)((FlagNum) / 3) * 100+100, null);
}
}
public class Flags extends JPanel {
/**
* Creates new form Flags
*/
public Flags(){
initComponents();
FlagSet.add(new Flag(1));
final Timer timer =new Timer(10, new ActionListener(){
#Override
public void actionPerformed(final ActionEvent e){
repaint();
for (Flag f: FlagSet){
f.Update();
}
}
});
}
public static ArrayList<Flag> FlagSet = new ArrayList();
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
for (Flag f: FlagSet){
f.Draw(g);
}
}
I then try to add flags like so:
flagCounter = 4;
while(flagCounter > -1){
Flags.FlagSet.add(new Flag(flagCounter));
flagCounter--;
}
Which works fine but my image doesn't change if I put in a Flgas.FlageSet.remove(//Some flag)later on. Any ideas? Thanks in advance.
It looks like you're missing a call to repaint().
Repaint is a signal sent to the drawing component to tell it that something has changed, and that it needs to call the paint methods again. In this case, as your addition to your Flags list will change how it is drawn, you should simply call repaint() after you've finished adding your flags.
the Code is below. right now what it does is it constantly moves the letter and I only want it to move a over one character when I press the next letter instead of going over more. Also the x+=2 is another method I used and It also didn't work.. This is basically supposed to be a typing class... Please help.It also places all the letters in the same place.. I need it to place them one space apart and I can't press the same letter twice or it just moves the letter
public class Type_Client extends Applet implements KeyListener,Runnable
{
boolean pickA,pickB,pickC,pickD,pickE,pickF,pickG,pickH,pickI,pickJ,pickK=false;
boolean pickL,pickM,pickN,pickO,pickP,pickQ,pickR,pickS,pickT,pickU,pickV=false;
boolean pickW,pickX,pickY,pickZ=false;
boolean space=false;
boolean run=true;
int x=10;
Type t1;
Thread thr;
public void init()
{
t1 = new Type();
thr=new Thread(this);
thr.start();
addKeyListener(this);
}
public void keyTyped(KeyEvent k)
{
}
public void keyReleased(KeyEvent k)
{
}
public void keyPressed(KeyEvent k)
{
if(k.getKeyCode()==KeyEvent.VK_A)
{
pickA=true;
k.consume();
}
if(k.getKeyCode()==KeyEvent.VK_B)
{
pickB=true;
k.consume();
}
if(k.getKeyCode()==KeyEvent.VK_C)
{
pickC=true;
k.consume();
}
if(k.getKeyCode()==KeyEvent.VK_SPACE)
{
space=true;
k.consume();
//Spce++;
}
}
public void run()
{
while(run==true)
{
try{
Thread.sleep(20);
}
catch(Exception e){};
repaint();
}
}
public void paint(Graphics g)
{
if(pickA)
{
g.drawString(" a",x,10);
}
if(pickB)
{
g.drawString(" b",x,10);
x++;
x++;
}
if(pickC)
{
g.drawString(" c",x,10);
x++;
x++;
}
}
}
public void stop()
{
}
public void start()
{
}
}
There are many problems with your code.
First, the infinite repaint loop:
public void run() {
while(run==true) {
try {
Thread.sleep(20);
}
catch(Exception e) { };
repaint();
}
}
This is bad. Remove it and the thread that starts it!
You only need to repaint the JFrame/JPanel/Applet when something changes in how the application will draw itself (or when the window geometry changes or the window is exposed, but the toolkit already handles all of those cases).
Ok, so when does something change? Possibly any time you press a key.
public void keyPressed(KeyEvent k) {
// Your existing code here
repaint();
}
Instead of repainting every 20ms you are now only repainting after a key is pressed. This is probably still too often. Shift, Alt, Ctrl, Meta, Caps Lock are all keys; if you press any of those, a repaint will be triggered despite your application not processing any of those keys. But at least is a minor inefficiency.
Second, x is a field instead of a local paint variable. It is initialized to 10 when the application starts, and incremented when paint is called.
g.drawString(" b",x,10);
Will draw the string " b" at (10,10) when the application is started and VK_B is pressed. But the next time redraw is called (20ms later with your existing code), it will draw it at (12,10), and then (14, 10), and then (16, 10), and so on.
Instead, you probably want:
public void paint(Graphics g) {
int x = 10;
// Remainder of paint code ...
}
So that each time paint is called, it draws the same way (unless something changes in the applications state which causes paint to intentionally draw differently).
drawString uses pixel coordinates. The letter "A" is more than 2 pixels wide in any legible font. For example, in this ASCII art, the letters "A" and "B" are 5 "pixels" wide. To leave a gap between the letters, "B" would need to be drawn at least 6 pixels to the right of "A".
* ****
* * * *
* * ****
***** * *
* * * *
* * ****
<-7px->
You can use Graphics#getFontMetrics to determine how much to advance the position of each character based on the preceding characters, with a given font.
Or, you could use a constant advance of (say) 16 pixels.
private final static int ADVANCE = 16;
public void paint(Graphics g) {
int x = 10;
if (pickA) {
g.drawString("a", x, 10);
x += ADVANCE;
}
if (pickB) {
g.drawString("b", x, 10);
x += ADVANCE;
}
// ...
}
Or you could let the toolkit do the work for you, and draw a String.
public void paint(Graphics g) {
StringBuilder sb = new StringBuilder(27);
if (pickA) {
sb.append("a ");
}
if (pickB) {
sb.append("b ");
}
// ... remainder cases ...
g.drawString(sb.toString(), 10, 10);
}
Finally, your 26 pick(Letter) variables are just plain awful. Consider a different method of recording which keys have been pressed.
Some options:
boolean picked [] = new boolean[26]; // boolean array (1 per letter)
Set<Integer> picked = new HashSet<>(); // A set of VK_ codes
Set<Character> picked = new HashSet<>(); // A set of characters
BitSet picked = new BitSet(26); // A set of bits (1 per letter)
Here is the smallest working example I can make for you. Adapt as needed.
#SuppressWarnings("serial")
public class Type_Client extends Applet {
private String typed = "";
private KeyAdapter adapter = new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
char ch = e.getKeyChar();
if (ch >= ' ' && ch <= '~') {
typed += ch;
repaint();
}
}
};
#Override
public void start() {
addKeyListener(adapter);
}
#Override
public void stop() {
removeKeyListener(adapter);
}
#Override
public void paint(Graphics g) {
super.paint(g);
g.drawString(typed, 10, 10);
}
}
I'm trying to understand how BufferStrategy is working. I've made a simple app that is drawing some Sprite objects over and over again every 60 frames per second. I can see the images on the canvas but they are flickering for some reason. Can you tell me why? If you don't want to read all the code, just focus on the Paint method and the main game loop.
public abstract class Frame extends JFrame implements KeyListener {
private static final long serialVersionUID = 1L;
//------------------------Variables------------------------//
private boolean initialized = false;
private boolean fullScreen = false;
public boolean running = true;
private GraphicsDevice vc;
private BufferStrategy strategy;
private Graphics2D g2d;
private int timer = 0;
//------------------------Variables------------------------//
public final void __init__() {
this.addKeyListener(this); //Adding key listener.
this.setVisible(true);
this.setIgnoreRepaint(true);
this.createBufferStrategy(2);
this.strategy = this.getBufferStrategy();
this.setResizable(false);
this.initialized = true; //Initialized.
}
//Create a window.
public final void set_mode(int width, int height, boolean fullScreen) throws NotInitializedException {
//Frame not initialized.
if (!this.initialized) {
throw new NotInitializedException("Frame not initialized!");
} else {
//--------------------Variables--------------------//
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
//--------------------Variables--------------------//
//Setting vc equal to the default graphics device of the system.
this.vc = env.getDefaultScreenDevice();
//Full Screen.
if (fullScreen) {
this.fullScreen = fullScreen;
//Creating the display mode.
DisplayMode mode = new DisplayMode(width, height, 32, DisplayMode.REFRESH_RATE_UNKNOWN);
//If display settings are allow to change display mode.
if (this.vc.isDisplayChangeSupported()) {
this.vc.setDisplayMode(mode); //Change to the new mode.
}
//Set the screen to full screen.
this.vc.setFullScreenWindow(this);
} //Not full screen.
else {
this.setSize(width, height);
this.addWindowListener(new WindowHandler(this));
}
}
}
//This mehod is been called from Sprite.draw() method.
public void paint(Sprite sprite) {
do {
do {
this.g2d = (Graphics2D) this.strategy.getDrawGraphics();
g2d.drawImage(sprite.getImage(), sprite.getX(), sprite.getY(), sprite.getWidth(), sprite.getHeight(), null);
this.g2d.dispose();
} while (this.strategy.contentsRestored());
this.strategy.show();
} while (this.strategy.contentsLost());
}
public final int tick(int fps) {
int ms = 1000 / fps;
timer += 1;
//Try to sleep.
try {
Thread.sleep(ms);
} //Thread interrupted.
catch (Exception e) {
System.out.println(e.getMessage());
System.exit(0);
}
return timer;
}
public class MyApp extends Frame {
public static String BG_PATH = "C:/Users/admin/Desktop/game/bg.jpg";
public static String PL_PATH = "C:/Users/admin/Desktop/game/player.png";
public static String EN_PATH = "C:/Users/admin/Desktop/game/enemy.png";
private int speed = 20;
private boolean left = false;
private boolean right = false;
#Override
public void keyPressed(KeyEvent arg0) {
// TODO Auto-generated method stub
if (arg0.getKeyCode() == KeyEvent.VK_LEFT) {
this.left = true;
} else if (arg0.getKeyCode() == KeyEvent.VK_RIGHT) {
this.right = true;
} else if (arg0.getKeyCode() == KeyEvent.VK_ESCAPE) {
this.close();
}
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
if (arg0.getKeyCode() == KeyEvent.VK_LEFT) {
this.left = false;
} else if (arg0.getKeyCode() == KeyEvent.VK_RIGHT) {
this.right = false;
}
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void onWindowClose() {
// TODO Auto-generated method stub
}
//This method starts the game.
public void startApp() {
this.__init__(); //initialize the frame.
Sprite bg = new Sprite(this, Picture.load(BG_PATH), "bg"); //Create a new sprite obj
this.set_mode(bg.getWidth() - 500, bg.getHeight() - 100, false); //Create the window.
Sprite player = new Sprite(this, Picture.load(PL_PATH), "player");
player.setX(bg.getWidth() / 3);
player.setY(bg.getHeight() / 2);
//Game Main Loop
while (this.running) {
bg.draw();
player.draw();
player.moveHorizontal(left, right, speed); //Dont worry about this line.
this.tick(50);
}
}
}
}
You have a few issues that I can clearly spot.
First off, you must understand that drawing in Swing/Awt is not known for it's speed, it's actually known for the exact opposite. The fact is, even though you're telling your game to run at 60fps, it probably can't do it. Thus the flickering. Essentially, your application is caught within a "drawing-data race", and it's always slightly behind. Try something real quick; set Thead.Sleep() to 10 or 30. I feel as though that might solve your problem entirely.
If not, consider the second problem. You're calling this.strategy.show(); inside the player.Draw(); function, when it needs to be the last thing that you do in your draw call. In other words:
//Game Main Loop
while (this.running) {
bg.draw(); // DON'T SWAP BUFFERS!
player.draw(); // DON'T SWAP BUFFERS!
// draw other entities
player.moveHorizontal(left, right, speed); //Dont worry about this line.
this.tick(50);
this.strategy.show(); // This needs to be the very last thing you do. You're swapping buffers here, which only needs to be done once per frame.
}
My guess is you're also swapping your buffer during the bg.Draw(); function as well, and that is actually why your screen is flickering. So those are two things right there. Try lowering the frames per second down to something that Java can actually handle, and don't swap your buffer until the VERY end of your drawing routine.
Some other recommendations:
Use direct variable access instead of getters and setters. There is overhead when calling "player.getX()". When you could just call "player.x".
There is no future in Java 2D game development. Swing/AWT(which you're using) is entirely dead. If you want to make a game, and be serious about it, take the time to learn OpenGL(In your case it would be Lwjgl as a wrapper).
For some reason when i run this program instead of outputting one card choice I get 3, sometimes four.
I'm trying to pick a name from the array list include it in the path, then output the image, you can see the result with the system out.
Heres the code:
public class Main {
public static void main (String[] args) {
Main.createScreen();
}
public static void createScreen() {
JFrame p = new JFrame("Angora Realms");
p.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GameGUI g = new GameGUI();
p.add(g);
p.setLocationRelativeTo(null);
p.pack();
p.setVisible(true);
}
}
Here's where i create the GUI and also the paint:
#SuppressWarnings("serial")
public class GameGUI extends JPanel implements ActionListener {
public Button drawCard = new Button("Draw Card");
public GameGUI() {
drawCard.addActionListener(this);
add(drawCard);
}
#Override
public void actionPerformed(ActionEvent event) {
Object cause = event.getSource();
if (cause == drawCard) {
System.out.println("Ay");
repaint();
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Cards c = new Cards();
g.drawImage(c.getImage(), 0, 0, 450, 700, this);
}
}
And here is where i choose what card to load:
public class Cards {
static Random random = new Random();
public static String getCard() {
String card = null;
String[] possibleCards = new String[] {"Cheetah", "Lion"};
card = possibleCards[random.nextInt(2)];
System.out.println(card);
return card;
}
public Image getImage() {
Image img = null;
try {
img = ImageIO.read(getClass().getResource("/dev/angora/images/plains/" + Cards.getCard() + ".png"));
}
catch (IOException e) {
e.printStackTrace();
}
return img;
}
}
When I run the code I get 4 system print outs of a random variation of Cheetah and Lion. I've been told before that I'm actually creating 3 instances of my code somewhere, but I have no idea where...
You don't entirely get to decide how and when paintComponent() gets executed, and that usually doesn't matter, because all the method is supposed to do is to paint the component. It gets called when you do a repaint(), but it also gets called when Swing thinks the UI needs to get updated (which can be when the window changes focus, it gets resized or a bunch of other reasons).
However, you've given it some responsibility that it shouldn't haveāto instantiate Cards.
Move Cards c = new Cards(); from paintComponent() into actionPerformed(ActionEvent event) where it belongs and you should be fine.
how else could i input a variable into the graphics method?
In general, you have a setter method and then you save the data as an instance variable in your class that the painting method can reference.. This is how methods like setBackground(...), setForeground(...), setFont(...) work.
So maybe you have a method like drawCard(...) in your class that will get a random card and set your "image" instance variable. Then you invoke repaint() in the drawCard() method so the component can repaint itself.
The component, not the application should be responsible for painting itself when a property of the component changes.
I'm trying to design a game like BeJeweled using java language
This is where I've reached so far :
public class Game {
public static void main(String[] args) throws InterruptedException {
final JFrame window = new JFrame();
window.setSize(508,669);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final Grid g=new Grid();
Game.obj(g);
window.add(g);
window.setVisible(true);
window.setResizable(false);
window.repaint(2);
window.addMouseListener(new MouseListener(){
#Override
public void mouseClicked(MouseEvent e) {
int x=e.getX();
int y=e.getY();
for(int i=0;i<10;i++) {
for(int j=0;j<16;j++){
if(x>i*50+5 && x<i*50+54 && y>j*40+26 && y<j*40+26+39){
g.b[i][j]=g.a[i][j];
int q = x;
int w=y;
int r =x;
int t =y;
q-=50;
w-=40;
if( i>0&&g.a[i-1][j]==g.b[i][j]){
g.a[i][j]=0;
g.a[i-1][j]=0;
}
if( j>0&&g.a[i][j-1]==g.b[i][j]){
g.a[i][j]=0;
g.a[i][j-1]=0;
}
r+=50;
t+=40;
if(i<9&&g.a[i+1][j]==g.b[i][j]){
g.a[i][j]=0;
g.a[i+1][j]=0;
}
if(j<15&&g.a[i][j+1]==g.b[i][j]){
g.a[i][j]=0;
g.a[i][j+1]=0;
}
}
}
}
SwingUtilities.updateComponentTreeUI(window);
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
});
}
public static void obj(Grid g){
Random r =new Random();
for(int k=0;k<10;k++)
for(int l=0;l<16;l++)
g.a[k][l]=1+r.nextInt(4);
}
}
class Grid extends JPanel {
private Graphics Graphics;
#Override
public void paint(Graphics g) {
final Graphics g1 = g ;
this.setGraphics(g);
for(int i=0;i<600;i+=50)
for(int j=0;j<400;j+=40)
g.drawRect(i, j, i+50, j+40);
for(int i=0;i<10;i++)
for(int j=0;j<16;j++){
if(a[i][j]== 0) g.setColor(Color.WHITE);
if(a[i][j] == 1) g.setColor(Color.ORANGE);
if(a[i][j] == 2) g.setColor(Color.red);
if(a[i][j] == 3) g.setColor(Color.GREEN);
if(a[i][j] == 4) g.setColor(Color.cyan);
g.fillRect(i*50+1, j*40+1, 49, 39);
}
// Mouselis mouseptr = new Mouselis(g);
// this.addMouseListener(mouseptr);
// this.addMouseMotionListener(mouseptr);
}
public void setGraphics(Graphics Graphics) {
this.Graphics = Graphics;
}
int [][] a= new int[10][16];
int [][] b= new int[10][16];
}
In this design only the up down left right of rectangles are being checked for same color in the method mouse clicked. How can i make it check all the near rectangles for the one having same color ?
Please help Thanks
You have four if statements that check the adjacent rectangles for the same color as the one that was clicked. Here is the last one:
if(j<15&&g.a[i][j+1]==g.b[i][j]){
g.a[i][j]=0;
g.a[i][j+1]=0;
}
j, the vertical grid coordinate, is compared with 15 to be sure that j+1 is within bounds. Also, a rectangle in the 2d-array a is checked to see if it is equal to the rectangle in the 2d-array b that got clicked. If it is, you set it to 0 for Color.WHITE. Because the indices are i and j+1 this checks the rectangle directly below the clicked one.
To check a rectangle that is diagonally adjacent, change both indices by one.
The rectangle to the bottom right is g.a[i+1][j+1]. To access this rectangle without an error you need to be sure that both i+1 and j+1 are within the bounds of the array to avoid an error.
So, the if statement is
if(j<15 && i < 9 && g.a[i+1][j+1]==g.b[i][j]){ ...
You can figure out the rest.
Java is a strong Object-Oriented programming language - especially before Java8: I think that you should really work with more Objects that would hold their own responsibilities and behaviours.
Once you'll have a class that represents a Jewel, just implement some recursive method to know if it's part of some "Jewel streak". For example:
public class Jewel {
private final JewelType type; // Could be an Enum for example
// Many other stuff to add (like a constructor at least!)
public Collection<Jewel> getStreak() {
final Set<Jewel> res = new HashSet<>();
this._getStreak(res);
return res;
}
private void _getStreak(final Set<Jewel> streak) {
// Just leave the method if we've already visited this Jewel
if(!streak.add(this)) {
return;
}
// Assuming that this method returns a Collection of the Jewels that are stored West, North, South and East from this
for(final Jewel neighbour : Grid.getInstance().getJewelsAround(this)) {
if(neighbour.getJewelType().equals(this.getJewelType())) {
neighbour._getStreak(streak);
}
}
}
}
When trying to see if some Jewel is part of a streak that is long enough to be "destroyed", just check something like this:
Jewel b = Grid.getInstance().getJewelForCoordinates(x, y);
final Collection<Jewel> streak = b.getStreak();
if(streak.size() >= Game.MINIMUM_STREAK_SIZE) {
Grid.getInstance().destroyJewels(streak);
}
I just don't even have access to any Java editor/compiler right now so please excuse me, would my code present any mistyping. Even though I recommend to do many changes, I hope it can help you :)
By the way, if you don't want to override all the methods described by the MouseListener interface, use the following:
window.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(final MouseEvent event) {
// Code to be executed on mouseClicked().
}
});
MouseAdapter is an abstract class that implements MouseListener and does nothing when receiving any event. You just have to override the methods that handle the events you're interested in ;)