I'm currently trying to make a reset button for my java platformer game using the enter key from the keyboard. The way that my level loads is as a BufferedImage object passed through a method I named LoadImageLevel. What I have tried to do is simply say
if(key == KeyEvent.VK_ENTER){ LoadImageLevel(level)}
where level is my BufferedImage object storing the level. This does reset the level upon pressing the key, but once the level is reset a few times the game gets ridiculously slow and the character can't move because it is so slow.
I'm thinking this is because every time I reset the level it just puts the images on top of each other until it's doing too much at once so it slows up the game.
I've been looking around to see if there is a way to clear out the previous BufferedImages each time I reset the level so that it only runs 1 image at a time thus keeping the game up to speed... I hope. Unfortunately there is no clear() or remove() method in the BufferedImage class and I have not been able to make one.
Any help will be appreciated, thanks!
package com.tim.neon.window;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
//import java.awt.event.KeyEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.util.Random;
//import com.tim.neon.framework.GameObject;
import com.tim.neon.framework.KeyInput;
import com.tim.neon.framework.ObjectId;
import com.tim.neon.objects.Block;
import com.tim.neon.objects.Player;
//Developed by Timothy O'Leary with much help from RealTutsGML
public class Game extends Canvas implements Runnable {
/**
*
*/
private static final long serialVersionUID = 5023365827045558937L;
private boolean running = false;
private Thread thread;
public static int WIDTH, HEIGHT;
private BufferedImage level = null;
Handler handler;
Camera cam;
Random rand = new Random();
private void init(){
WIDTH = getWidth();
HEIGHT = getHeight();
BufferedImageLoader loader = new BufferedImageLoader();
level = loader.loadImage("/level2.png");//loading the level
handler = new Handler();
cam = new Camera(0, 0);
LoadImageLevel(level);
this.addKeyListener(new KeyInput(handler));
}
public synchronized void start(){
if(running)
return;
running = true;
thread = new Thread(this);
thread.start();
}
public void run(){
init(); //
this.requestFocus(); //
long lastTime = System.nanoTime();
double amountOfTicks = 60.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
long timer = System.currentTimeMillis();
int updates = 0;
int frames = 0;
while(running){
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >= 1){
tick();
updates++;
delta--;
}
render();
frames++;
if(System.currentTimeMillis() - timer > 1000){
timer += 1000;
System.out.println("FPS: " + frames + " Ticks: " + updates);
frames = 0;
updates = 0;
}
}
}
private void tick(){
handler.tick();
for(int i = 0; i < handler.object.size(); i++){
if(handler.object.get(i).getId() == ObjectId.Player){
cam.tick(handler.object.get(i));
}
}
}
private void render(){
BufferStrategy bs = this.getBufferStrategy();
if(bs == null){
this.createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
Graphics2D g2d = (Graphics2D) g;
//////////////////////////
//draw here
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
g2d.translate(cam.getX(), cam.getY());//begin of cam
handler.render(g);
g2d.translate(-cam.getX(), -cam.getY());//end of cam
/////////////////////////
g.dispose();
bs.show();
}
private void LoadImageLevel(BufferedImage image){//function to load levels drawn pixel by pixel in paint
int w = image.getWidth();
int h = image.getHeight();
System.out.println("width, height:" + " " + w + " " + h);
for(int xx = 0; xx < h; xx++){
for(int yy = 0; yy < w; yy++){
int pixel = image.getRGB(xx, yy);
int red = (pixel >> 16) & 0xff;
int green = (pixel >> 8) & 0xff;
int blue = (pixel) & 0xff;
if(red == 255 && green == 255 && blue == 255) handler.addObject(new Block(xx*32, yy*32, ObjectId.Block));
if(red == 0 && green == 0 && blue == 255) handler.addObject(new Player(xx*32, yy*32,handler, ObjectId.Player));
}
}
}
public static void main(String args[]){
new Window(800, 600, "Neon Platform Game Prototype", new Game());
}
}
package com.tim.neon.framework;
import java.awt.Component;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import com.tim.neon.objects.Block;
import com.tim.neon.objects.Player;
import com.tim.neon.window.BufferedImageLoader;
import com.tim.neon.window.Game;
import com.tim.neon.window.BufferedImageLoader;
import com.tim.neon.window.Handler;
import com.tim.neon.window.Game;
import com.tim.neon.window.Window;
public class KeyInput extends KeyAdapter {
Handler handler;
//public BufferedImage level = null;//i added
public KeyInput(Handler handler){
this.handler = handler;
}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
//BufferedImageLoader loader = new BufferedImageLoader();///
//level = loader.loadImage("/level2.png");//loading the level///
for(int i = 0; i < handler.object.size(); i++){
GameObject tempObject = handler.object.get(i);
if(tempObject.getId() == ObjectId.Player){
if(key == KeyEvent.VK_D) tempObject.setVelX(5);
if(key == KeyEvent.VK_A) tempObject.setVelX(-5);
if(key == KeyEvent.VK_SPACE && !tempObject.isJumping()){//for double jump do if(key == KeyEvent.VK.SPACE) tempObject.setVelY(-15)
tempObject.setJumping(true);
tempObject.setVelY(-15);//change number to increase or decrease jump height
}
}
}
if(key == KeyEvent.VK_ESCAPE){
System.exit(1);
}
//if(key == KeyEvent.VK_ENTER){/// trying to make reset button
// level.repaint();
//}///
}
public void keyReleased(KeyEvent e){
int key = e.getKeyCode();
for(int i = 0; i < handler.object.size(); i++){
GameObject tempObject = handler.object.get(i);
if(tempObject.getId() == ObjectId.Player){
if(key == KeyEvent.VK_D) tempObject.setVelX(0);
if(key == KeyEvent.VK_A) tempObject.setVelX(0);
}
}
}
/*private void LoadImageLevel(BufferedImage image){// this function is used in both this clas and the Game class
int w = image.getWidth();
int h = image.getHeight();
System.out.println("width, height:" + " " + w + " " + h);
for(int xx = 0; xx < h; xx++){
for(int yy = 0; yy < w; yy++){
int pixel = image.getRGB(xx, yy);
int red = (pixel >> 16) & 0xff;
int green = (pixel >> 8) & 0xff;
int blue = (pixel) & 0xff;
if(red == 255 && green == 255 && blue == 255) handler.addObject(new Block(xx*32, yy*32, ObjectId.Block));
if(red == 0 && green == 0 && blue == 255) handler.addObject(new Player(xx*32, yy*32,handler, ObjectId.Player));
}
}
}*/
}
Related
Im not sure if this problem has come up with anyone else, but Im doing some simple animation things. Im trying to have a transparent background, which has been easy to make with the following code:
jf.setBackground(new Color(0,0,0,0));
The problem is, whenever the thing im trying to move moves(a shrek picture in my case), it constantly paints and isnt clearing the previous shreks. Ill post all my code down below.
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import java.io.*;
import java.util.logging.*;
import java.util.logging.*;
import javax.imageio.*;
public class MoveTest extends JPanel implements KeyListener {
double velX = 0;
double velY = 0;
double moveX = 0;
double moveY = 0;
double posX = 1;
double posY = 1;
double friction = 1.005;
BufferedImage image;
public void paintComponent(Graphics g) {
super.paintComponent(g);
try{
image = ImageIO.read(new File("shrek.png"));
}catch (IOException ex){
System.out.println("Image Does Not Exist");
}
g.setColor(Color.RED);
moveX += velX;
moveY += velY;
posX += moveX;
posY += moveY;
g.drawImage(image,(int)posX,(int)posY,null);
}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
int up = KeyEvent.VK_UP, w = KeyEvent.VK_W;
int down = KeyEvent.VK_DOWN, s = KeyEvent.VK_S;
int left = KeyEvent.VK_LEFT, a = KeyEvent.VK_A;
int right = KeyEvent.VK_RIGHT, d = KeyEvent.VK_D;
if(key == w || key == up)
velY = -.2;
if(key == s || key == down)
velY = .2;
if(key == a || key == left)
velX = -.2;
if(key == d || key == right)
velX = .2;
}
public void keyReleased(KeyEvent e){
int key = e.getKeyCode();
int up = KeyEvent.VK_UP, w = KeyEvent.VK_W;
int down = KeyEvent.VK_DOWN, s = KeyEvent.VK_S;
int left = KeyEvent.VK_LEFT, a = KeyEvent.VK_A;
int right = KeyEvent.VK_RIGHT, d = KeyEvent.VK_D;
if(key == w || key == up)
velY = 0;
if(key == s || key == down)
velY = 0;
if(key == a || key == left)
velX = 0;
if(key == d || key == right)
velX = 0;
}
public void keyTyped(KeyEvent e){}
public static void main(String[] args) {
MoveTest mt = new MoveTest();
JFrame jf = new JFrame();
jf.setTitle("Test one cladss");
jf.setSize(1440,900);
jf.setBackground(new Color(0,0,0,0));
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.add(mt);
jf.setVisible(true);
mt.setOpaque(true);
mt.addKeyListener(mt);
mt.requestFocusInWindow();
while(true){
//jf.removeAll();
jf.repaint();
mt.collision();
mt.friction();
try {
Thread.sleep(16);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
public void collision(){
if(posX >= 1440-50|| posX <= 0){
velX -= (2*velX);
moveX -= (2*moveX);
}
if(posY >= 900-50 || posY <= 0){
velY -= (2*velY);
moveY -= (2*moveY);
}
}
public void friction(){
moveX /= friction;
moveY /= friction;
}
}
If you anything more information please comment it. Any help is appreciated!
I have run into this before. The paintComponent method overridden from a JFrame is different than overriding from all other components. Since you have overriden the JFrame's paint code, it is no longer erasing the background. There are two solution:
Add your own JComponent (JPanel would work well) and override it's paint methods instead of the JFrames.
or
Clear the canvas yourself as the first thing you do after you call super.paintComponent.
In Addition:
You should not be reading your image every time you paint. Since painting happens soon after repaint is called from any thread, the image could load many many times. If you need to load it once, create a nameless instance block in the class like so:
{
try{
image = ImageIO.read(new File("shrek.png"));
}catch (IOException ex){
System.out.println("Image Does Not Exist");
}
}
If you are only ever going to have one copy, make it a static block:
static {
<load image here>
}
If you want to reload the image every frame because it changes you need to find a way not to do that. Instead any image animation should happen by editing the BufferImage object in java or loading a sprite-map.
I have trouble with performance when I am rotating every image, when drawing it FPS has dropped from 1400 to 6. Can I rotate BufferedImage object just after creating it, so the calculation happens only once?
There is my Grid Control class: (Drawing class, problem method is drawRotated())
package cs.meowxiik.universes.graphics;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.util.Observer;
import cs.meowxiik.universes.map.Map;
import cs.meowxiik.universes.map.Tile;
public class GridControl {
int width;
int height;
int xcells;
int ycells;
int cellWidth;
int cellHeight;
int maxZoom = 80;
int minZoom = 30;
private Map activeMap;
public GridControl(int width, int height, int xcells, int ycells) {
this.width = width;
this.height = height;
this.xcells = xcells;
this.ycells = ycells;
cellWidth = width / xcells;
cellHeight= height/ ycells;
}
public GridControl(int width, int height, int cellWidth, int cellHeight, int thisDoesntMatterJustForOverloading) {
this.width = width;
this.height = height;
this.cellWidth = cellWidth;
this.cellHeight = cellHeight;
xcells = width / cellWidth;
ycells = height / cellHeight;
}
public void drawGrid(Graphics g){
for(int i = 0; i < xcells; i++){
for(int ii = 0; ii <ycells; ii++){
g.drawRect(i * cellWidth, ii * cellHeight, cellWidth, cellHeight);
}
}
}
public int getCellSize() {
return cellWidth;
}
public void editCellSize(int i) {
if(i == 0)return;
System.out.println("Resizing: " + i);
//Pokud je i menší jak 0 -> člověk se pokouší přibližovat
if(i < 0 && xcells > maxZoom)return;
if(i > 0 && xcells < minZoom)return;
this.cellWidth += i;
this.cellHeight += i;
xcells = width / cellWidth;
ycells = height / cellHeight;
}
public void setActiveMap(Map map){
this.activeMap = map;
}
public void drawMap(Graphics g, Canvas canvas){
if(activeMap != null){
for(int i = 0; i < xcells; i++){
for(int ii = 0; ii <ycells; ii++){
drawRotated(activeMap.getTiles()[i][ii].getTexture(),activeMap.getTiles()[i][ii].getDegrees(), i*cellWidth, ii*cellWidth,canvas, g, null);
//ImageObserver observer = null;
//g.drawImage(activeMap.getTiles()[i][ii].getTexture(), i*cellWidth, ii*cellWidth, observer);
}
}
}
}
public Tile getTileByCoordinate(int x, int y){
int cellx = x / this.cellWidth;
int celly = y / this.cellHeight;
return activeMap.getTiles()[cellx][celly];
}
public boolean isWalkable(int x, int y){
return getTileByCoordinate(x,y).getWalkable();
}
public void drawRotated(BufferedImage img,double rotationRequired,int x,int y,Canvas canvas, Graphics g, Observer observer){
//double rotationRequired = Math.toRadians(degrees);
double locationX = img.getWidth() / 2;
double locationY = img.getHeight() / 2;
AffineTransform tx = AffineTransform.getRotateInstance(rotationRequired, locationX, locationY);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
// Drawing the rotated image at the required drawing locations
g.drawImage(op.filter(img, null), x, y, null);
}}
My Tile method:
public class Tile {
boolean walkable;
BufferedImage image;
double radians;
int ID; //0 - floor, 1 - wall
public Tile(boolean walkable, BufferedImage image, int ID) {
this.walkable = walkable;
this.image = image;
this.ID = ID;
}
public BufferedImage getTexture() {
return image;
}
public boolean getWalkable() {
return walkable;
}
public int getDegrees() {
return (int) Math.toDegrees(radians);
}
public int getID() {
return ID;
}
public void setTexture(BufferedImage image, int degrees) {
this.image = image;
this.radians = Math.toRadians(degrees);
}
}
And my Map creator: (the rotating part is broken, I'll fix that later, now I need to solve my 6-FPS problem)
package cs.meowxiik.universes.map;
import cs.meowxiik.universes.graphics.GraphicsManager;
public class MapCreator {
GraphicsManager graphics;
public MapCreator(GraphicsManager graphics) {
this.graphics = graphics;
}
public Map getSpaceStationMap(){
Map map;
int x = 32;
int y = 18;
Tile[][] tiles = new Tile[x][y];
for(int i = 0; i < x; i++){
for(int ii = 0; ii < y; ii++){
tiles[i][ii] = new Tile(true, graphics.floor, 0);
}
}
for(int i = 0; i < x; i++){
for(int ii = 0; ii < y; ii++){
if(i == 0 || ii == 0 || i == x-1 || ii == y-1)tiles[i][ii] = new Tile(false,graphics.stWallZero, 1); //tiles.get(i).set(ii, new Tile(false,graphics.wall));
}
}
for(int i = 0; i < x; i++){
for(int ii = 0; ii < y; ii++){
if(tiles[i][ii].getID() == 0)break;
boolean connectedUp = false;
boolean connectedLeft = false;
boolean connectedRight = false;
boolean connectedBottom = false;
if(i + 1 < tiles.length)
if(tiles[i + 1][ii + 0].getID() == 1)
connectedRight = true;
if(i != 0)
if(tiles[i - 1][ii + 0].getID() == 1)
connectedLeft = true;
if(ii + 1 < tiles[i].length)
if(tiles[i + 0][ii + 1].getID() == 1)
connectedBottom = true;
if(ii != 0)
if(tiles[i + 0][ii - 1].getID() == 1)
connectedUp = true;
if(connectedUp && !(connectedLeft || connectedRight || connectedBottom))tiles[i][ii].setTexture(graphics.stWallOne, 0);
if(connectedLeft && !(connectedUp || connectedRight || connectedBottom))tiles[i][ii].setTexture(graphics.stWallOne, 90);
if(connectedRight && !(connectedUp || connectedLeft || connectedBottom))tiles[i][ii].setTexture(graphics.stWallOne, 180);
if(connectedBottom && !(connectedUp || connectedRight || connectedLeft))tiles[i][ii].setTexture(graphics.stWallOne, 270);
if((connectedUp && connectedBottom) && !(connectedLeft || connectedRight))tiles[i][ii].setTexture(graphics.stWallTwo, 90);
if(!(connectedUp && connectedBottom) && !(connectedLeft || connectedRight))tiles[i][ii].setTexture(graphics.stWallTwo, 0);
}
}
map = new Map(x,y,tiles);
return map;
}
}
Given this code
public void drawRotated(BufferedImage img,double rotationRequired,int x,int y,Canvas canvas, Graphics g, Observer observer) {
//double rotationRequired = Math.toRadians(degrees);
double locationX = img.getWidth() / 2;
double locationY = img.getHeight() / 2;
AffineTransform tx = AffineTransform.getRotateInstance(rotationRequired, locationX, locationY);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
BufferedImage rotatedImage = op.filter(img, null); // my edit here
// Drawing the rotated image at the required drawing locations
g.drawImage(rotatedImage , x, y, null);
}
The rotation of the image to get rotatedImage is only dependant upon it's size (width/height) and the required rotation.
From my reading of your code the required rotation is largely fixed. The rotation is known when the setTexture method of Title is called.
Sine this is the case, rotatedImage can be computed in the setTexture method. Just create a new attribute that stores the computed rotated image. Don't destroy the original.
If setTexture is called as often as drawRotated then this won't deliver the performance increase you desire.
This is my game project. It's very simple version of "Flappy Bird" and I have some serious problems with how the collisions algorithm works. I wrote 2 separate code fragments for collision, for wall1 and wall2. The problem begins when the ball is trying to go through a hole because somehow the program is detecting a collision with a wall. I'm almost positive that the collision algorithm was written correctly because I have been checking it all day.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import java.util.Timer;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Game extends Applet implements KeyListener, Runnable {
Image bground;
Random generator = new Random();
int r1;
int wall1x;
int wall1y;
int wall1long;
int wall2x;
int wall2y;
int wall2long;
Timer timer;
private Image i;
private Graphics doubleG;
int r2;
int blok_x1 = 800;
int blok_y1;
int blok_x = 800;
int blok_y = 0;
int blok_x_v = 2;
int ballX = 20;
int ballY = 20;
int dx = 0;
int dyclimb = 1;
int dyrise = 1;
double gravity = 3;
double jumptime = 0;
int FPS = 100;
public int tab[];
public boolean grounded = true, up = false;
boolean OVER = false;
#Override
public void init() {
bground = getImage(getCodeBase(), "12.png");
this.setSize(600, 400);
tab = new int[100];
for (int t = 0; t < 100; t++) {
tab[t] = generator.nextInt(380) + 1;
}
addKeyListener(this);
}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
ballX -= 10;
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
ballX += 10;
}
if (e.getKeyCode() == KeyEvent.VK_UP) {
ballY -= 10;
up = true;
}
if (e.getKeyCode() == KeyEvent.VK_DOWN) {
ballY += 10;
}
}
#Override
public void paint(Graphics g) {
g.drawImage(bground, 0, 0, this);
if (OVER == false) {
for (int i = 0; i < 100; i++) {
g.setColor(Color.green);
wall1x = blok_x + i * 400;
wall1y = blok_y;
wall1long = tab[i];
g.fillRect(wall1x, wall1y, 20, wall1long);
g.setColor(Color.green);
wall2x = blok_x1 + i * 400;
wall2y = tab[i] + 60;
wall2long = 400 - tab[i];
g.fillRect(wall2x, wall2y, 20, wall2long);
g.setColor(Color.green);
}
g.setColor(Color.red);
g.fillOval(ballX, ballY, 20, 20);
} else {
g.drawString("GAME OVER", 300, 300);
}
}
#Override
public void update(Graphics g) {
if (i == null) {
g.setColor(Color.green);
i = createImage(this.getSize().width, this.getSize().height);
doubleG = i.getGraphics();
g.setColor(Color.green);
}
doubleG.setColor(getBackground());
g.setColor(Color.green);
doubleG.fillRect(0, 0, this.getSize().width, this.getSize().height);
doubleG.setColor(getForeground());
g.setColor(Color.green);
paint(doubleG);
g.drawImage(i, 0, 0, this);
}
#Override
public void run() {
int time = 10;
while (true) {
if (up == true) {
ballY -= dyclimb;
time--;
} else {
ballY += dyrise;
}
if (time == 0) {
time = 10;
up = false;
}
blok_x--;
blok_x1--;
if (ballX > 600 || ballX < 0 || ballY > 400 || ballY < 0) {
OVER = true;
}
for (int i = 0; i < 100; i++) { // collision algorithm
wall1x = blok_x + i * 400;
wall1y = blok_y;
wall1long = tab[i];
if (ballX + 20 >= wall1x && ballX <= wall1x + 20 && ballY <= wall1y + wall1long && ballY >= wall1x - 20) { //wall1
OVER = true;
}
}
for (int i = 0; i < 100; i++) {
wall2x = blok_x1 + i * 400;
wall2y = tab[i] + 60;
wall2long = 400 - tab[i];
if (ballX + 20 >= wall2x && ballX <= wall2x + 20 && ballY <= wall2y + wall2long && ballY >= wall2x - 20) { //wall2
OVER = true;
}
}
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException ex) {
Logger.getLogger(NewApplet.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
#Override
public void start() {
Thread thread = new Thread(this);
thread.start();
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
}
Use Rectangle class. There's a method called Intersect or Intersection or something like that.
Say you have one object moving. Make a Rectangle to match the object in position(basically an invisible cover for the object).
Do the same things with another object.
When both are to collide, use the intersection method to check on the collision by using the rectangles.
These might help
http://docs.oracle.com/javase/7/docs/api/java/awt/Rectangle.html
Java method to find the rectangle that is the intersection of two rectangles using only left bottom point, width and height?
java.awt.Rectangle. intersection()
I was making a snake game, it works fine on my computer but doesn't work on any of the school computers. It compiles and I can run it but my keypressed events don't work, so i cannot control the snake because the keys don't work.
Snake Class
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.Timer;
public class Snake implements ActionListener, KeyListener
{
public static Snake snake;
public JFrame jframe;
public RenderPanel renderPanel;
public Timer timer = new Timer(20, this);
public ArrayList<Point> snakeParts = new ArrayList<Point>();
public static final int UP = 0, DOWN = 1, LEFT = 2, RIGHT = 3, SCALE = 10;
public int ticks = 0, direction = DOWN, score, tailLength = 10, time;
public Point head, mouse;
public Random random;
public boolean over = false, paused;
public Dimension dim;
public Snake()
{
dim = Toolkit.getDefaultToolkit().getScreenSize();
jframe = new JFrame("TechnoSnake");
jframe.setVisible(true);
jframe.setSize(805, 700);
jframe.setResizable(false);
jframe.setLocation(dim.width / 2 - jframe.getWidth() / 2, dim.height / 2 - jframe.getHeight() / 2);
jframe.add(renderPanel = new RenderPanel());
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.addKeyListener(this);
startGame();
}
public void startGame()
{
over = false;
paused = false;
time = 0;
score = 0;
tailLength = 1;
ticks = 0;
direction = DOWN;
head = new Point(0, -1);
random = new Random();
snakeParts.clear();
mouse = new Point(random.nextInt(79), random.nextInt(66));
timer.start();
}
public void actionPerformed(ActionEvent arg0)
{
renderPanel.repaint();
ticks++;
if (ticks % 2 == 0 && head != null && !over && !paused)
{
time++;
snakeParts.add(new Point(head.x, head.y));
if (direction == UP)
if (head.y - 1 >= 0 && noTailAt(head.x, head.y - 1))
head = new Point(head.x, head.y - 1);
else
over = true;
if (direction == DOWN)
if (head.y + 1 < 67 && noTailAt(head.x, head.y + 1))
head = new Point(head.x, head.y + 1);
else
over = true;
if (direction == LEFT)
if (head.x - 1 >= 0 && noTailAt(head.x - 1, head.y))
head = new Point(head.x - 1, head.y);
else
over = true;
if (direction == RIGHT)
if (head.x + 1 < 80 && noTailAt(head.x + 1, head.y))
head = new Point(head.x + 1, head.y);
else
over = true;
if (snakeParts.size() > tailLength)
snakeParts.remove(0);
if (mouse != null)
{
if (head.equals(mouse))
{
score += 10;
tailLength++;
mouse.setLocation(random.nextInt(79), random.nextInt(66));
}
}
}
}
public boolean noTailAt(int x, int y)
{
for (Point point : snakeParts)
{
if (point.equals(new Point(x, y)))
{
return false;
}
}
return true;
}
public static void main(String[] args)
{
snake = new Snake();
}
public void keyPressed(KeyEvent e)
{
int i = e.getKeyCode();
if ((i == KeyEvent.VK_A || i == KeyEvent.VK_LEFT) && direction != RIGHT)
direction = LEFT;
if ((i == KeyEvent.VK_D || i == KeyEvent.VK_RIGHT) && direction != LEFT)
direction = RIGHT;
if ((i == KeyEvent.VK_W || i == KeyEvent.VK_UP) && direction != DOWN)
direction = UP;
if ((i == KeyEvent.VK_S || i == KeyEvent.VK_DOWN) && direction != UP)
direction = DOWN;
if (i == KeyEvent.VK_SPACE)
if (over)
startGame();
else
paused = !paused;
}
public void keyReleased(KeyEvent e)
{
}
public void keyTyped(KeyEvent e)
{
}
}
RenderPanel Class
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import javax.swing.JPanel;
public class RenderPanel extends JPanel
{
//public static Color green = new Color(1666073);
public static Color brown = new Color(6697728);
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
//g.setColor(green);
g.setColor(Color.BLACK);
g.fillRect(0, 0, 800, 700);
Snake snake = Snake.snake;
g.setColor(Color.BLUE);
for (Point point : snake.snakeParts)
{
g.fillRect(point.x * Snake.SCALE, point.y * Snake.SCALE, Snake.SCALE, Snake.SCALE);
}
g.fillRect(snake.head.x * Snake.SCALE, snake.head.y * Snake.SCALE, Snake.SCALE, Snake.SCALE);
g.setColor(Color.RED);
g.fillRect(snake.mouse.x * Snake.SCALE, snake.mouse.y * Snake.SCALE, Snake.SCALE, Snake.SCALE);
String string = "Score: " + snake.score + ", Length: " + snake.tailLength + ", Time: " + snake.time / 20;
g.setColor(Color.white);
g.drawString(string, (int) (getWidth() / 2 - string.length() * 2.5f), 10);
string = "Game Over!";
if (snake.over)
g.drawString(string, (int) (getWidth() / 2 - string.length() * 2.5f), (int) snake.dim.getHeight() / 4);
string = "Paused!";
if (snake.paused && !snake.over)
g.drawString(string, (int) (getWidth() / 2 - string.length() * 2.5f), (int) snake.dim.getHeight() / 4);
}
}
You really shouldn't be adding a KeyListener to a JFrame. A JFrame consists of the frame, a JRootPane, which has a content pane (and now your RenderPanel) and possibly a glass pane ontop it. All of those could be stealing focus away from the frame which means it will never be able to respond to key events
KeyListener will only raise key events if the component it is registered to is focusable AND has focus.
Try using key bindings instead. They provide better control over the focus level required to generate the key event
EDIT:
OH!!!!!
it works!!!
It seems that at one point it was fixed However the wrong HTML file was opening up so the wrong code was running. I feel stupid, that should have been obvious.
But THANKYOU!!!
Its so awesome to actually get some help with this stuff. whenever i ask for some help anywhere else or even ask my teacher im usually ignored or get useless advice.
(end of edit)
Im making a game for my final project in a java class. I just got mouse aiming to work using AffineTransform, however When ever the player object rotates to 90 degrees(or a multiple of it), it does this weird stutter thing.
Heres the code im specifically concerned with.
g2.drawImage(img, x_pos,y_pos,this);
AffineTransform oldTransform = g2.getTransform();
g2.setTransform(AffineTransform.getRotateInstance(radAngle,x_pos + (img.getWidth() / 2),y_pos+(img.getHeight() / 2)));
Could someone please help me figure out how to fix this? my project is due tomorrow so im slim on time.
Here are the images i use
Heres the code.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.lang.Math.*;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import javax.imageio.ImageIO;
import java.io.*;
import java.net.URL;
public class Game extends Applet implements Runnable, KeyListener, MouseMotionListener
{
int x_pos = 250;
int y_pos = 250;
float x_speed = 0;
float y_speed = 0;
int radius = 20;
int appletsize_x = 800;
int appletsize_y = 600;
int x = 0;
int y = 0;
int up = 0;
int down= 0;
int left = 0;
int right= 0;
int mouse_x;
int mouse_y;
int tracking_angle;
private BufferedImage dbImage;
private Graphics dbg;
private Image curser;
BufferedImage img = null;
BufferedImage round = null;
AffineTransform at = new AffineTransform();
double radAngle;
public void init()
{
try {
URL url = new URL(getCodeBase(), "Player.png");
img = ImageIO.read(url);
} catch (IOException e) {System.out.println("Cant find player image");
}
try {
URL url = new URL(getCodeBase(), "round.png");
round = ImageIO.read(url);}
catch (IOException e) {}
setBackground (Color.blue);
setFocusable(true);
addKeyListener( this );
curser = getImage(getDocumentBase(), "mouse.png");
addMouseMotionListener(this);
try
{
Toolkit tk = Toolkit.getDefaultToolkit();
Cursor c = tk.createCustomCursor( curser,new Point( 5, 5 ), "Inodrop" );
setCursor( c );
}
catch( IndexOutOfBoundsException x )
{}
}
public class Shot {
int x_loc = -50;
int y_loc = -50;
public Shot(){
if(x_loc < 0){
x_loc = x_pos;}
if(y_loc < 0){
y_loc = y_pos;}
paint(dbg);}
public void paint(Graphics g){
System.out.println("hi");
Graphics2D g2d = (Graphics2D)g;
Graphics g2D = round.getGraphics();
g2d.drawImage(round, x_loc,y_loc,null);}}
public void start ()
{
Thread th = new Thread (this);
th.start ();
}
public void stop()
{
}
public void destroy()
{
}
public void mouseMoved(MouseEvent e){
//get position of mouse
mouse_x = e.getX();
mouse_y = e.getY();
double x_dist = mouse_x - x_pos;
double y_dist = mouse_y - y_pos;
if (x_dist == 0) {
radAngle = 90;
} else if ((x_dist == 0) && (y_dist == 0)) {
radAngle = 0;
} else {
radAngle = Math.atan(y_dist / x_dist);
}
tracking_angle = (int)(Math.sin(radAngle) * 100);
//System.out.println(Math.toRadians(tracking_angle));
}
public void mouseDragged(MouseEvent e){}
public void keyReleased(KeyEvent r)
{
//Left
if (r.getKeyCode() == 39 ){
x = 0;
left = 0;
Shot shoot = new Shot();
}
//Right
if (r.getKeyCode() == 37){
x = 0;
right = 0;
}
//Down
if (r.getKeyCode() == 38 ) {
//y_speed = 0;
down = 0;}
//Up
if (r.getKeyCode() == 40 ) {
//y_speed = 0;
up = 0;}
//move();
}
public void keyTyped(KeyEvent t){}
public void keyPressed(KeyEvent r){
//Left
if (r.getKeyCode() == 39 ){
left = 1;}
//Right
if (r.getKeyCode() == 37){
right = 1;}
//Down
if (r.getKeyCode() == 38 ) {
down = 1;}
//Up
if (r.getKeyCode() == 40 ) {
up = 1;}
//move();
}
public void run ()
{
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
while (true)
{
if (left == 1 && x_speed < 11){
x = 0;
x_speed += 1;
}
//Right
if (right == 1 && x_speed > -11){
x = 0;
x_speed -= 1;
}
//Down
if (down == 1 && y_speed > -11) {
y_speed -= 1;}
//Up
if (up == 1 && y_speed < 11) {
y_speed += 1;}
if( x == 0 && x_speed > 0){
x_speed -=.2;}
if( x == 0 && x_speed < 0){
x_speed +=.2;}
if( y == 0 && y_speed > 0){
y_speed -=.2;}
if( y == 0 && y_speed < 0){
y_speed +=.2;}
if (x_pos > appletsize_x - radius && x_speed > 0)
{
x_pos = radius;
}
else if (x_pos < radius && x_speed < 0)
{
x_pos = appletsize_x + radius ;
}
//System.out.println(y_pos);
if (y_pos > appletsize_y - radius && y_speed > 0){
y_speed = 0;}
else if ( y_pos < radius && y_speed < 0 ){
y_speed = 0;}
x_pos += (int)x_speed;
y_pos += (int)y_speed;
repaint();
try
{
Thread.sleep (15);
}
catch (InterruptedException ex)
{
}
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
}
}
public void update (Graphics g)
{
if (dbImage == null)
{
dbImage = new BufferedImage(this.getSize().width, this.getSize().height, BufferedImage.TYPE_INT_RGB);
dbg = dbImage.getGraphics ();
}
dbg.setColor (getBackground ());
dbg.fillRect (0, 0, this.getSize().width, this.getSize().height);
dbg.setColor (getForeground());
paint (dbg);
g.drawImage (dbImage, 0, 0, this);
}
public void paint (Graphics g)
{
//g = img.getGraphics();
Graphics2D g2 = (Graphics2D)g;
g2.drawImage(img, x_pos,y_pos,this);
AffineTransform oldTransform = g2.getTransform();
g2.setTransform(AffineTransform.getRotateInstance(radAngle,x_pos + (img.getWidth() / 2),y_pos+(img.getHeight() / 2)));
System.out.println(img.getWidth());
}
}
double x_dist = mouse_x - x_pos;
double y_dist = mouse_y - y_pos;
double radAngle = Math.atan(y_dist / x_dist);
tracking_angle = (int) (Math.sin(radAngle) * 100);
I think the error is somewhere in this part. You're definitely dividing by 0 here if x_dist is 0. Better do something like this:
if (x_dist == 0) {
radAngle = 90;
} else {
radAngle = Math.atan(y_dist / x_dist);
}
EDIT: Additionally, I think you should throw away the tracking_angle line completely and just do this later:
g2.setTransform(AffineTransform.getRotateInstance(rad_angle,
x_pos + (img.getWidth() / 2),y_pos+(img.getHeight() / 2)));
Also you should change that new code you posted in the comments:
double radAngle;
if (x_dist == 0) {
radAngle = 90;
} else if (y_dist == 0) {
radAngle = 90;
} else {
radAngle = Math.atan(y_dist / x_dist);
}
You are solving this for x_dist == 0 or y_dist == 0 (which isn't an edge case), but not for the case that both are 0 where you simply can't compute an angle and I think you should go with 0. So use this instead:
double radAngle;
if (x_dist == 0) {
radAngle = 90;
} else if ((x_dist == 0) && (y_dist == 0)) {
radAngle = 0;
} else {
radAngle = Math.atan(y_dist / x_dist);
}
Also, as trashgod pointed out, you're ignoring exceptions, for example:
try {
URL url = new URL(getCodeBase(), "Player.png");
img = ImageIO.read(url);
} catch (IOException e) {
}
You should not just continue in such cases but f.e. display an useful error message and quit the program, in any case do something instead of just catching the exception and continue as if nothing happened.
I haven't tested this, but try:
double radAngle = Math.atan2(y_dist, x_dist);