I have an error it everytime I try to start it, it comes up with a blank window and these error messages.
Exception in thread "Thread-2" java.lang.IllegalArgumentException: Color parameter outside of expected range: Red Green
at java.awt.Color.testColorValueRange(Unknown Source)
at java.awt.Color.<init>(Unknown Source)
at java.awt.Color.<init>(Unknown Source)
at java.awt.Color.<init>(Unknown Source)
at com.tutorial.main.HUD.render(HUD.java:32)
at com.tutorial.main.Game.render(Game.java:118)
at com.tutorial.main.Game.run(Game.java:85)
at java.lang.Thread.run(Unknown Source)
I have a suspicion it is something to do with rendering but not sure can someone help.
I have inserted the following codes:
Game
Window
SmartEnemy
HUD
ID
Handler
package com.tutorial.main;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.util.Random;
public class Game extends Canvas implements Runnable {
private static final long serialVersionUID = 7580815534084638412L;
public static final int WIDTH = 640, HEIGHT = WIDTH / 12 * 9;
private Thread thread;
private boolean running = true;
private Random r;
private Handler handler;
private HUD hud;
private Spawn spawner;
public Game() {
new Window(WIDTH, HEIGHT, "Lets Build a Game!", this);
handler = new Handler();
hud = new HUD();
spawner = new Spawn(handler, hud);
this.addKeyListener(new KeyInput(handler));
r = new Random();
// for(int i = 0; i <1; i++){
//implementing Player1
handler.addObject(new Player(WIDTH / 2 - 32, HEIGHT / 2 - 32, ID.Player, handler));
handler.addObject(new BasicEnemy(r.nextInt(Game.WIDTH), r.nextInt(Game.HEIGHT), ID.BasicEnemy, handler));
//implementing Player2
//handler.addObject(new Player(WIDTH/2-32, HEIGHT/2+64, ID.Player2));
/*for (int i = 0; i < 1; i++){
//implementing BasicEnemy
handler.addObject(new BasicEnemy(r.nextInt(WIDTH), r.nextInt(HEIGHT), ID.BasicEnemy, handler));
}*/
}
public synchronized void start() {
thread = new Thread(this);
thread.start();
}
public synchronized void stop() {
try {
thread.join();
running = false;
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
this.requestFocus();
long lastTime = System.nanoTime();
double amountOfTicks = 60.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
long timer = System.currentTimeMillis();
int frames = 0;
while (running) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while (delta >= 1) {
tick();
delta--;
}
if (running) {
render();
frames++;
if (System.currentTimeMillis() - timer > 1000) {
timer += 1000;
//System.out.println("FPS: " + frames);
frames = 0;
}
}
}
}
private void tick() {
handler.tick();
hud.tick();
spawner.tick();
}
private void render() {
BufferStrategy bs = this.getBufferStrategy();
if (bs == null) {
this.createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.setColor(Color.BLACK);
g.fillRect(0, 0, WIDTH, HEIGHT);
handler.render(g);
hud.render(g);
g.dispose();
bs.show();
}
public static float clamp(float
var, float min, float max) {
if (var >= max) {
return var = max;
} else if (var <= min) {
return var = min;
} else {
return var;
}
}
public static void main(String args[]) {
Game game = new Game();
game.start();
}
}
package com.tutorial.main;
import java.awt.Canvas;
import javax.swing.*;
import java.awt.Dimension;
public class Window extends Canvas {
private static final long serialVersionUID = -240840600533728354L;
public Window(int width, int height, String title, Game game) {
JFrame frame = new JFrame(title);
frame.setPreferredSize(new Dimension(width, height));
frame.setMinimumSize(new Dimension(width, height));
frame.setMaximumSize(new Dimension(width, height));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.add(game);
frame.setVisible(true);
}
}
package com.tutorial.main;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
public class SmartEnemy extends GameObject{
private Handler handler;
private GameObject player;
public SmartEnemy(int x, int y, ID id, Handler handler) {
super(x, y, id);
this.handler = handler;
for(int i = 0; i < handler.object.size(); i++){
if(handler.object.get(i).getId() == ID.Player) player = handler.object.get(i);
}
}
public Rectangle getBounds(){
return new Rectangle((int)x, (int)y, 32, 32);
}
public void tick() {
handler.addObject(new Trail(x, y,ID.Trail, Color.GREEN, 16, 16, 0.02f, handler));
x += velX;
y += velY;
float diffX = x - player.getX() - 8;
float diffY = y - player.getY() - 8;
float distance = (float) Math.sqrt((x - player.getX()) * (x - player.getX()) + (y - player.getY()) * (y - player.getY()));
velX = (float) ((-1.0/distance) * diffX);
velY = (float) ((-1.0/distance) * diffY);
if (y <= 0 || y >= Game.HEIGHT - 37) velY *= -1;
if (x <= 0 || x >= Game.WIDTH - 16) velX*= -1;
}
public void render(Graphics g) {
g.setColor(Color.GREEN);
g.fillRect((int)x, (int)y, 16, 16);
}
}
package com.tutorial.main;
import java.awt.Graphics;
import java.util.LinkedList;
public class Handler {
LinkedList < GameObject > object = new LinkedList < GameObject > ();
public void tick() {
for (int i = 0; i < object.size(); i++) {
GameObject tempObject = object.get(i);
tempObject.tick();
}
};
public void render(Graphics g) {
for (int i = 0; i < object.size(); i++) {
GameObject tempObject = object.get(i);
tempObject.render(g);
}
}
public void addObject(GameObject object) {
this.object.add(object);
}
public void removeObject(GameObject object) {
this.object.remove(object);
}
}
package com.tutorial.main;
import java.awt.Color;
import java.awt.Graphics;
public class HUD {
public static float HEALTH = 100;
private float greenValue = 255;
private int level = 1;
private float score = 0;
public void tick(){
HEALTH = Game.clamp(HEALTH, 0, 100);
greenValue = Game.clamp(greenValue, 0, 255);
greenValue = HEALTH*2;
score++;
}
public void render(Graphics g){
//Background for Health bar
g.setColor(Color.gray);
g.fillRect(15, 15, 200, 32);
//Health Bar
g.setColor(new Color(75, (float) greenValue, 0));
g.fillRect(15, 15, (int) (HEALTH * 2), 32);
g.setColor(Color.WHITE);
g.drawRect(15, 15, 200, 32);
g.drawString("Score: " + score, 15, 60);
g.drawString("Level: " + level, 15, 75);
}
/*int level = 1, point = 0;
//point scoring system
for(int i = 2; i > 1; i++){
if(HEALTH > 0){
point++;
System.out.println(point);
}
}
}*/
private void score(float score){
this.score = score;
}
public float getScore(){
return score;
}
public int getLevel(){
return level;
}
public void setLevel(int level){
this.level = level;
}
}
package com.tutorial.main;
import java.awt.Graphics;
import java.awt.Rectangle;
public abstract class GameObject {
protected float x, y;
protected ID id;
protected float velX, velY;
public GameObject(float x, float y, ID id){
this.x = x;
this.y = y;
this.id = id;
}
public abstract void tick();
public abstract void render(Graphics g);
public abstract Rectangle getBounds();
public void setX(int x){
this.x = x;
}
public void setY(int y){
this.y = y;
}
public int getX(){
return (int) x;
}
public int getY(){
return (int) y;
}
public void setId(ID id){
this.id = id;
}
public ID getId(){
return id;
}
public void setVelX(int velX){
this.velX = velX;
}
public void setVelY(int velY){
this.velY = velY;
}
public float getVelX(){
return velX;
}
public float getVelY(){
return velY;
}
}
The excetion is caused by this constructor call:
new Color(75, (float) greenValue, 0)
You use the Color(float, float, float), since the second parameter has type float. As documented in the javadocs, this constructor takes 3 floats that represent rgb components. Ranges are from 0.0f to 1.0f, not from 0 to 255, which is why you get the error (75 is too large).
It seems like you should not cast the second parameter to make that statement use the Color(int, int, int) constructor.
Related
I have been working on a flappy bird clone so I can get more practice programming. Everything in the game works, however the game has frame skips and lag drops, and I do not know how to make Java programs run more smoothly. Am I supposed to measure the amount of time a method takes and try to shorten that, or do I do something else? I have seen people explain how to program Java games, but there is hardly anything on improving the performance. Any advice would be helpful. Thank you.
Hazards class
package entity;
import java.util.ArrayList;
public class Hazards {
public ArrayList<Horizontal> hors;
public ArrayList<Vertical> verts;
public Hazards(int width, int height, int thickness) {
hors = new ArrayList<Horizontal>();
hors.add(new Horizontal(0, 0, width, thickness));
hors.add(new Horizontal(0, height-thickness, width, thickness));
verts = new ArrayList<Vertical>();
}
}
Horizontal class
package entity;
import java.awt.Rectangle;
public class Horizontal {
public int xPos, yPos, width, height;
public Rectangle bounds;
public Horizontal(int x, int y, int w, int h) {
this.xPos = x;
this.yPos = y;
this.width = w;
this.height = h;
this.bounds = new Rectangle(x, y, w, h);
}
public void updateBounds(int x, int y, int w, int h) {
this.xPos = x;
this.yPos = y;
this.width = w;
this.height = h;
this.bounds = new Rectangle(x, y, w, h);
}
}
Vertical class
package entity;
import java.awt.Rectangle;
import java.util.Random;
public class Vertical {
public int xPos, width, gapSize, gapPos;
public boolean scoredOn = false;
public Rectangle top, bottom;
public Vertical(int xPos, int width, int roofHeight, int floorHeight, int gapSize) {
this.xPos = xPos;
this.width = width;
this.gapPos = new Random().nextInt(floorHeight - gapSize) + roofHeight;
this.top = new Rectangle();
this.bottom = new Rectangle();
this.top.setBounds(xPos, 0, width, gapPos);
this.bottom.setBounds(xPos, gapPos + gapSize, width, floorHeight - roofHeight + top.height + gapSize);
}
}
Content class
package main;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.JPanel;
public class Content extends JPanel {
private static final long serialVersionUID = 1L;
private Engine e;
private Rectangle bounds;
public Content(Engine engine) {
e = engine;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.clearRect(0, 0, this.getWidth(), this.getHeight());
// Roof and floor
g.setColor(Color.black);
for (int x = 0; x < e.e.hors.size(); x++) {
bounds = e.e.hors.get(x).bounds;
g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
}
// Pipes
g.setColor(Color.black);
for(int x = 0; x < e.e.verts.size(); x++) {
bounds = e.e.verts.get(x).top;
g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
bounds = e.e.verts.get(x).bottom;
g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
}
// Player
g.setColor(Color.black);
g.fillRect((int) e.p.xPos, (int) e.p.yPos, e.p.size, e.p.size);
// Score
g.setColor(Color.blue);
g.setFont(new Font("Monospaced", Font.PLAIN, 40));
g.drawString(Integer.toString(e.p.score), e.width/2, 80);
}
}
Engine class
package main;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import entity.Hazards;
import entity.Vertical;
import screen.TitleScreen;
public class Engine implements Runnable {
public JFrame f;
public String title = "Flappy Bird";
public int width = 500, height = 500;
public Content c;
public boolean running = false;
public boolean playing = false;
public Thread t;
public Player p;
public Hazards e;
public TitleScreen ts;
public JPanel mainPanel;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Engine e = new Engine();
e.execute();
}
});
}
public void execute() {
ts = new TitleScreen(width, height);
e = new Hazards(width, height, 30);
p = new Player(this);
c = new Content(this);
c.setPreferredSize(new Dimension(width, height));
c.setLayout(null);
c.addKeyListener(p);
mainPanel = new JPanel();
mainPanel.setPreferredSize(new Dimension(width, height));
mainPanel.setLayout(null);
f = new JFrame();
f.setTitle(title);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setResizable(false);
f.add(c);
// f.add(mainPanel);
f.pack();
f.createBufferStrategy(2);
f.setLayout(null);
f.setLocationRelativeTo(null);
f.setVisible(true);
c.requestFocus();
//ts.setScreen(mainPanel);
start();
}
public synchronized void start() {
if (running)
return;
running = true;
t = new Thread(this);
t.start();
}
public synchronized void stop() {
if (!running)
return;
running = false;
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
long lastime = System.nanoTime();
double AmountOfTicks = 60;
double ns = 1000000000 / AmountOfTicks;
double delta = 0;
int tick = 0;
while (running) {
long now = System.nanoTime();
delta += (now - lastime) / ns;
lastime = now;
if (delta >= 1) {
// Call all updates here
if (playing) {
p.updatePos();
tick++;
if (tick == 60) {
tick = 0;
p.distance += p.speed;
System.out.println(p.distance);
if ((p.distance % 4) == 0) {
System.out.println("Making new pipes-----------------------------------------------------");
e.verts.add(new Vertical(600, 10, 30, height - 30, 100));
}
}
for (int x = 0; x < e.verts.size(); x++) {
e.verts.get(x).top.x -= p.speed;
e.verts.get(x).bottom.x -= p.speed;
if(e.verts.get(x).top.x<-50) {
e.verts.remove(x);
System.out.println("removed a pipe");
}
if(p.xPos>e.verts.get(x).top.x && !e.verts.get(x).scoredOn) {
e.verts.get(x).scoredOn = true;
p.score++;
}
}
}
mainPanel.revalidate();
mainPanel.repaint();
f.revalidate();
f.repaint();
delta--;
}
}
}
}
Player class
package main;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Player implements KeyListener {
public int size = 10;
public double xPos = 50;
public double yPos = 240;
public double gravity = 3.4;
public double jumpForce = 16.6;
public double weight = 1;
public int speed = 2;
public int score = 0;
public int distance = 0;
public boolean jumping = false;
public double jumpTime = 10;
public int timed = 0;
public Rectangle bounds, temp, top, bottom;
public Engine en;
public Player(Engine engine) {
en = engine;
bounds = new Rectangle((int)xPos, (int)yPos, size, size);
}
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_W && en.playing) {
jumping = true;
} else if (e.getKeyCode() == KeyEvent.VK_SPACE) {
en.playing = !en.playing;
}
if(jumping) {
timed = 0;
jumpForce = 16.6;
}
}
public void keyReleased(KeyEvent e) {
}
public void updatePos() {
// collide with floor or ceiling
for(int x = 0; x < en.e.hors.size(); x++) {
temp = en.e.hors.get(x).bounds;
if(bounds.intersects(temp)) {
en.playing = false;
jumping = false;
timed = 0;
jumpForce = 0;
yPos = 240;
score = 0;
en.e.verts.clear();
distance = 0;
gravity = 3.8;
}
}
// collide with pipe
for(int x =0; x <en.e.verts.size();x++) {
top = en.e.verts.get(x).top;
bottom = en.e.verts.get(x).bottom;
if(bounds.intersects(top)||bounds.intersects(bottom)) {
en.playing = false;
jumping = false;
timed = 0;
jumpForce = 0;
yPos = 240;
score = 0;
gravity =3.4;
en.e.verts.clear();
distance = 0;
}
}
if (jumping && en.playing) {
gravity = 3.4;
yPos -= jumpForce;
jumpForce -= weight;
if (jumpForce == 0) {
jumping = false;
jumpForce = 16.6;
}
}
//if(!jumping && en.playing) {
gravity += 0.1;
//}
System.out.println(gravity);
yPos += gravity;
bounds.setBounds((int)xPos, (int)yPos, size, size);
}
}
EDIT
: it seems that in my move() method, java has to skip one of the 2 if statements
Keeping it simple. I'm trying to make a GUI in java that models the following class Truck behavior: the blue squares are supposed to run up their diagonales, which they do. But when they are supposed to bounce back once they reach the edge point of the square they just fly away. I've placed a condition to prevent this, but it never passes. I'll upload GUI and Drawable, but I don't think they are needed.
Class Truck:
package construction_site;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.plaf.ButtonUI;
public class Truck extends Thread implements Drawable {
private boolean isFull = false;
private int x, y;
private int capacity;
private Panel panel;
static int r = 20;
private int dx, dy;
private Site site;
private Building building;
public Truck(int x, int y, Panel panel, Building building, Site site) {
this.x = x;
this.y = y;
this.building = building;
this.panel = panel;
this.site = site;
this.start();
}
public void setCapacity(int capacity) {
this.capacity = capacity;
}
#Override
public void run() {
super.run();
while (true) {
move();
panel.repaint();
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setDirection(int i) {
if (i == 0) {
dx = -1;
dy = -1;
}
if (i == 1) {
dx = 1;
dy = -1;
}
if (i == 2) {
dx = -1;
dy = 1;
}
if (i == 3) {
dx = 1;
dy = 1;
}
}
private void move() {
if (site.truckOnSite(x, y)) {
site.loadTruck(this);
dx *= -1;
dy *= -1;
}
if (building.containsTruck(this)) {
building.unloadTruck(this);
dx *= -1;
dy *= -1;
}
x += dx;
y += dy;
}
public int getDx() {
return dx;
}
public void setFull(boolean isFull) {
this.isFull = isFull;
}
#Override
public void draw(Graphics g) {
g.setColor(Color.BLUE);
if (isFull)
g.fillRect(x - 10, y - 10, r, r);
else
g.drawRect(x - 10, y - 10, r, r);
}
}
Class Panel:
package construction_site;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.ArrayList;
import javax.swing.JPanel;
public class Panel extends JPanel {
private ArrayList<Drawable> drawables = new ArrayList<>();
private Site site;
private Building[] buildings = new Building[4];
private Truck[] trucks = new Truck[4];
private Van[] vans = new Van[4];
public Panel(int w, int h) {
setPreferredSize(new Dimension(w, h));
site = new Site(100, 75, 500, 500, this);
drawables.add(site);
buildings[0] = new Building(100, 75, this);
buildings[1] = new Building(100 + 500, 75, this);
buildings[2] = new Building(100, 75 + 500, this);
buildings[3] = new Building(100 + 500, 75 + 500, this);
for (Building b : buildings)
drawables.add(b);
trucks[0] = new Truck(100 + 250, 75 + 250, this, buildings[0], site);
trucks[1] = new Truck(100 + 250, 75 + 250, this, buildings[1], site);
trucks[2] = new Truck(100 + 250, 75 + 250, this, buildings[2], site);
trucks[3] = new Truck(100 + 250, 75 + 250, this, buildings[3], site);
for (int i = 0; i < 4; i++)
trucks[i].setDirection(i);
for (Truck t : trucks)
drawables.add(t);
}
#Override
public void paint(Graphics g) {
super.paint(g);
for (Drawable d : drawables)
d.draw(g);
g.setColor(Color.GREEN);
for (int i = 1; i <= 3; i++)
g.drawLine(buildings[0].getX(), buildings[0].getY(), buildings[i].getX(), buildings[i].getY());
g.drawLine(buildings[1].getX(), buildings[1].getY(), buildings[2].getX(), buildings[2].getY());
}
}
Class Building:
package construction_site;
import java.awt.Color;
import java.awt.Graphics;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Building extends Thread implements Drawable {
private Panel panel;
private boolean done = false;
private int x, y;
static int w = 100;
static int h = 100;
private ReentrantLock lock = new ReentrantLock();
private Condition insufficientMaterial = lock.newCondition();
private Condition insufficientMisc = lock.newCondition();
private Condition sufficient = lock.newCondition();
private int material = 0;
private int misc = 0;
private int spent = 0;
public Building(int x, int y, Panel panel) {
this.x = x;
this.y = y;
this.panel = panel;
this.start();
}
#Override
public void run() {
super.run();
lock.lock();
while(material < 100 )
try {
insufficientMaterial.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
spent += 150;
misc -= 50;
material -= 100;
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void unloadVan(Van v) {
lock.lock();
System.out.println("Truck got in");
if (material >= 100 && misc >=50) {
}
misc += 50;
v.setCapacity(0);
insufficientMisc.signalAll();
lock.unlock();
}
public void unloadTruck(Truck t) {
lock.lock();
material += 10000;
t.setCapacity(0);
t.setFull(false);
insufficientMaterial.signalAll();
lock.unlock();
}
public void setMaterial(int material) {
this.material = material;
}
public void setMisc(int misc) {
this.misc = misc;
}
public boolean containsVan(int x2, int y2) {
return ( Math.sqrt((x - x2)*(x - x2) + (y - y2)*(y - y2)) <= h/2 );
}
public boolean containsTruck(Truck t) {
return (x == t.getX() && y == t.getY());
}
public int getX() {
return x;
}
public int getY() {
return y;
}
#Override
public void draw(Graphics g) {
g.setColor(Color.BLACK);
g.drawRect(x - 50, y - 50, 100, 100);
}
}
Class Site:
package construction_site;
import java.awt.Color;
import java.awt.Graphics;
public class Site implements Drawable {
private int x, y, w, h;
private Panel panel;
public Site(int x, int y, int w, int h, Panel panel) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.panel = panel;
}
public boolean contains(int x2, int y2) {
return (x == x2 && y == 2);
}
public boolean truckOnSite(int x2, int y2) {
return ( x2 == x + w / 2 && y2 == y + h / 2);
}
public boolean vanOnSite(int x2, int y2) {
return ( (x2 == x && y2 == y + h / 2) || (x2 == x + w && y2 == y + h / 2) );
}
public void loadVan(Van v) {
v.setCapacity(5000);
}
public void loadTruck(Truck t) {
t.setCapacity(10000);
t.setFull(true);
}
#Override
public void draw(Graphics g) {
g.setColor(Color.GRAY);
g.fillRect(x, y, w, h);
}
}
As it turned out much later, it doesn't seem truncation errors were the problem at hand. It was a mistake at setting the trucks' starting point and the condition that decides when they're supposed to turn the other way. What looked like the truck bouncing off, was actually the oppsoite truck from the same diagonal passing through. A simple change in direction of my Truck's move() method did the trick.
public void setDirection(int i) {
if (i == 0) {
dx = -1;
dy = -1;
}
if (i == 1) {
dx = 1;
dy = -1;
}
if (i == 2) {
dx = -1;
dy = 1;
}
if (i == 3) {
dx = 1;
dy = 1;
}
}
So, I am taking a Java tutorial from RealTutsGML, and I am on the last part of episode seven. I have a problem though - the enemy AI does not work as it should - it does not follow the player all the time, and when it does, it's jittery and only within short range. Also the enemy only moves towards the bottom right.
Here is all of my code: (The needed parts)
package com.project.main;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.util.Random;
public class Game extends Canvas implements Runnable{
private static final long serialVersionUID = -2379768900378456337L;
public static final int WIDTH = 640, HEIGHT = WIDTH / 12 * 9;
private Thread thread;
private boolean running = false;
private Random r;
private Handler handler;
private HUD hud;
private Spawn spawner;
public Game(){
handler = new Handler();
this.addKeyListener(new KeyInput(handler));
new Window(WIDTH, HEIGHT, "Dodge BETA", this);
hud = new HUD();
spawner = new Spawn(handler, hud);
r = new Random();
handler.addObject(new Player(WIDTH/2-32, HEIGHT/2-32, ID.Player, handler));
handler.addObject(new BasicEnemy(r.nextInt(WIDTH - 32), r.nextInt(HEIGHT - 32), ID.BasicEnemy, handler));
}
public synchronized void start(){
thread = new Thread(this);
thread.start();
running = true;
}
public synchronized void stop(){
try{
thread.join();
running = false;
}catch(Exception e){
e.printStackTrace();
}
}
public void run(){
this.requestFocus();
long lastTime = System.nanoTime();
double amountOfTicks = 60.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
long timer = System.currentTimeMillis();
int frames = 0;
while(running){
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >= 1){
tick();
delta--;
}
if(running)
render();
frames++;
if(System.currentTimeMillis() - timer > 1000){
timer += 1000;
System.out.println("FPS: " + frames);
}
}
stop();
}
private void tick(){
handler.tick();
hud.tick();
spawner.tick();
}
private void render(){
BufferStrategy bs = this.getBufferStrategy();
if(bs == null){
this.createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.setColor(Color.black);
g.fillRect(0, 0, WIDTH, HEIGHT);
handler.render(g);
hud.render(g);
g.dispose();
bs.show();
}
public static float clamp(float var, float min, float max){
if(var >= max)
return var = max;
else if(var <= min)
return var = min;
else
return var;
}
public static void main(String args[]){
new Game();
}
}
GameObject is the master class for the enemies and player. It assists using a lot of premade methods to make stuff easier and cleaner.
package com.project.main;
import java.awt.Graphics;
import java.awt.Rectangle;
public abstract class GameObject {
protected float x, y;
protected ID id;
protected float velX, velY;
public GameObject(float x, float y, ID id){
this.x = x;
this.y = y;
this.id = id;
}
public abstract void tick();
public abstract void render(Graphics g);
public abstract Rectangle getBounds();
public void setX(int x){
this.x = x;
}
public void setY(int y){
this.y = y;
}
public float getX(){
return x;
}
public float getY(){
return y;
}
public void setId(ID id){
this.id = id;
}
public ID getId(){
return id;
}
public void setVelX(int velX){
this.velX = velX;
}
public void setVelY(int velY){
this.velY = velY;
}
public float getVelX(){
return velX;
}
public float getVelY(){
return velY;
}
}
The Handler Class
This class helps add objects into the game and remove them, as well as updating them and rendering the object.
package com.project.main;
import java.awt.Graphics;
import java.util.LinkedList;
public class Handler {
LinkedList<GameObject> object = new LinkedList<GameObject>();
public void tick(){
for(int i = 0; i < object.size(); i++){
GameObject tempObject = object.get(i);
tempObject.tick();
}
}
public void render(Graphics g){
for(int i = 0; i < object.size(); i++){
GameObject tempObject = object.get(i);
tempObject.render(g);
}
}
public void addObject(GameObject object){
this.object.add(object);
}
public void removeObject(GameObject object){
this.object.remove(object);
}
}
THE SMARTENEMY AI CLASS is supposed to create the smart enemy that follows the player around - but as I previously explained, its really buggy.
package com.project.main;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
public class SmartEnemy extends GameObject{
private Handler handler;
private GameObject player;
public SmartEnemy(int x, int y, ID id, Handler handler) {
super(x, y, id);
this.handler = handler;
for(int i = 0; i < handler.object.size(); i++){
if(handler.object.get(i).getId() == ID.Player) player = handler.object.get(i);
}
}
public Rectangle getBounds(){
return new Rectangle((int)x, (int)y, 16, 16);
}
public void tick() {
x += velX;
y += velY;
float diffX = x - player.getX() - 8;
float diffY = y - player.getY() - 8;
float distance = (float) Math.sqrt((x - player.getX())*(x - player.getX()) + (y-player.getY())*(y-player.getY()));
velX = (int) ((-1.0/distance) * diffX);
velY = (int) ((-1.0/distance) * diffY);
if(y <= 0 || y >= Game.HEIGHT - 50) velY *= -1;
if(x <= 0 || x >= Game.WIDTH - 20) velX *= -1;
handler.addObject(new Trail(x, y, ID.Trail, Color.green, 16, 16, 0.03f, handler));
}
public void render(Graphics g) {
g.setColor(Color.green);
g.fillRect((int)x, (int)y, 16, 16);
}
}
A couple of things come to mind:
If it only moves right and down it indicates that your deltas are always positive (velX, velY). It's not apparent from the code i SMARTENEMY why this happens.
Secondly, as distance grows velocity will drop. This is probably why it only works on short distances.
Thirdly, if you flip the arguments for your diff calculation (player.x - x) you can drop the -1f on the velocity calculation.
I don't understand why the velocity should be dependent on the distance, though.
So I'm making very simple game. Game is about some guy who jumps on rocks(circles) and rocks sometimes get covered by water and when they are, you cant stand on them otherwise you'll fall into water and drown. I'm stuck in part where i need to make those rocks disappear(be covered by water). So I need at randomized time make them disappear, for random seconds(not too long) make them "invisible" and then again they need to show up. I'm still kinda beginner and I would appreciate any kind of answer but if you could explain it to me I'd be thrilled.
Here is my code:
My main class
package com.pitcher654.main;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyListener;
import java.awt.image.BufferStrategy;
import java.util.Random;
import com.pitcher654.main.Game.STATE;
public class Game extends Canvas implements Runnable{
private static final long serialVersionUID = -7800496711589684767L;
public static final int WIDTH = 640, HEIGHT = WIDTH / 12 * 9;
private Thread thread;
private boolean running = false;
private Random r;
private Handler handler;
//private HUD hud;
private Menu menu;
public enum STATE {
Menu,
Help,
Game
};
public STATE gameState = STATE.Menu;
public Game() {
handler = new Handler();
menu = new Menu(this, handler);
this.addKeyListener(new KeyInput(handler));
this.addMouseListener(menu);
new Window(WIDTH, HEIGHT, "My game", this);
//hud = new HUD();
r = new Random();
if(gameState == STATE.Game) {
//handler.addObject(new Player(100, 200, ID.Player));
}
//handler.addObject(new Player(100, 200, ID.Player));
//handler.addObject(new BasicEnemy(100, 200, ID.BasicEnemy));
}
public synchronized void start() {
thread = new Thread(this);
thread.start();
running = true;
}
public synchronized void stop() {
try {
thread.join();
running = false;
}catch(Exception ex) { ex.printStackTrace(); }
}
public void run()
{
this.requestFocus();
long lastTime = System.nanoTime();
double amountOfTicks = 60.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
long timer = System.currentTimeMillis();
int frames = 0;
while(running)
{
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >=1)
{
tick();
delta--;
}
if(running)
render();
frames++;
if(System.currentTimeMillis() - timer > 1000)
{
timer += 1000;
//System.out.println("FPS: "+ frames);
frames = 0;
}
}
stop();
}
private void tick() {
handler.tick();
//hud.tick();
if(gameState == STATE.Game) {
}else if(gameState == STATE.Menu) {
menu.tick();
}
}
private void render() {
BufferStrategy bs = this.getBufferStrategy();
if(bs == null) {
this.createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.setColor(new Color(87, 124, 212));
g.fillRect(0, 0, WIDTH, HEIGHT);
if(gameState == STATE.Game) {
g.setColor(new Color(209, 155, 29));
for(int i = 0; i < 5; i++) {
g.fillOval(80 + (100 * i), 325, 70, 20);
}
}else if(gameState == STATE.Menu || gameState == STATE.Help){
menu.render(g);
}
handler.render(g);
if(gameState == STATE.Game) {
}
//hud.render(g);
g.dispose();
bs.show();
}
public static int clamp(int var, int min, int max) {
if(var >= max)
return var = max;
else if(var <= max)
return var = min;
else
return var;
}
public static void main(String[] args) {
new Game();
}
}
My Player class where I create my player:
package com.pitcher654.main;
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import com.pitcher654.main.Game.STATE;
public class Player extends GameObject {
Random r = new Random();
public Player(int x, int y, ID id) {
super(x, y, id);
//velX = r.nextInt(5) + 1;
//velY = r.nextInt(5);
}
public void tick() {
x += velX;
y += velY;
//System.out.println(x);
if(x == 500) x = 500;
}
public void render(Graphics g) {
if(id == ID.Player) g.setColor(Color.white);
if(id == ID.Player2) g.setColor(Color.blue);
g.fillRect(x, y, 32, 32);
g.drawLine(x + 15, y, x + 15, y + 100);
g.drawLine(x + 15, y + 100, x, y + 135);
g.drawLine(x + 15, y + 100, x + 33, y + 135);
g.drawLine(x + 15, y + 70, x - 35, y + 30);
g.drawLine(x + 15, y + 70, x + 65, y + 30);
/*if(game.gameState == STATE.Menu) {
g.setColor(new Color(87, 124, 212));
g.fillRect(0, 0, Game.WIDTH, Game.HEIGHT);
}*/
}
}
And my game Object class:
package com.pitcher654.main;
import java.awt.Graphics;
public abstract class GameObject {
protected static int x, y;
protected ID id;
protected int velX, velY;
public GameObject(int x, int y, ID id) {
this.x = x;
this.y = y;
this.id = id;
}
public abstract void tick();
public abstract void render(Graphics g);
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setID(ID id) {
this.id = id;
}
public ID getID() {
return id;
}
public void setVelX(int velX) {
this.velX = velX;
}
public void setVelY(int velY) {
this.velY = velY;
}
public int getVelX() {
return velX;
}
public int getVelY() {
return velY;
}
}
If you need any other class, just tell me I'll post it.
You should store a status of every stone in the game.
So if you have given number of stones (5), create a constant field with this number. Then create an array of ### boolean values where you'll save status of each stone.
Then create an array of "times" when the stones will change their visibility.
private static final int NUM_STONES = 5; // you can change the # of the stones here
private boolean[] visible = new int[NUM_STONES];
private long[] changeTimes = new long[NUM_STONES];
In your game's init method initialize the values.
for(int i=0; i<NUM_STONES; i++){
visible[i] = true; // each stone will be visible
changeTimes[i] = System.currentTimeMillis() + r.nextInt(10000); // every stone will disappear in less than 10 seconds
}
In your update method (I suppose tick() ) update visibility statuses.
long now = System.currentTimeMillis();
for(int i=0; i<NUM_STONES; i++){
if(now < changeTimes[i]){ // if the time has come
if(visible[i]) changeTimes[i] = now + r.nextInt(5000); // every stone will be invisible up to five seconds
else changeTimes[i] = now + r.nextInt(10000); // every stone will be visible again up to 10 seconds
visible[i] = !visible[i]; // switch the visibility state
}
}
And finally add the condition to the render method:
if(gameState == STATE.Game) {
for(int i = 0; i < NUM_STONES; i++) {
if(visible[i] g.setColor(new Color(209, 155, 29));
else g.setColor(new Color(107, 155, 170));
g.fillOval(80 + (100 * i), 325, 70, 20);
}
}
That should be it.
Next thing you should do is extracting magic numbers into constants, like I showed you with the NUM_STONES. And also don't create a new instance of the Color class every time you render a stone and create instances of the colors just like I've written before.
Also notice that some stones will disappear (and appear again) for a very short time - you can add few seconds to the changeTimes[i] in your update method to ensure that each stone will be (in)visible at least for this amount of time.
I created a class that draws a ball on a screen and my goal is to move it with the keys, but the ball stays in one spot. the coordinates of the ball change according to the key presses but not the actual ball itself
import java.applet.Applet;
import java.awt.Color;
import java.awt.Component;
import java.awt.Event;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
public class game extends Applet implements Runnable
{
static final int WIDTH = 450;
static final int HEIGHT = 450;
private Image dbImage;
private Graphics dbg;
public static long NEW_DOT_FREQ = TimeUnit.SECONDS.toMillis(3);
public long lastUpdateTime;
public long timeSinceLastNewDot;
public ArrayList<Ball> BALLS;
Color[] color = {Color.red, Color.blue, Color.green, Color.yellow, Color.magenta, Color.black};
int colorIndex;
static final int NUM_OF_BALLS = 4;
int i;
int t;
MainBall mainBall = new MainBall(100, 100, 10, 10, 100, 100, 0, 0);
Thread updateTime = new updateTime();
public void start()
{
lastUpdateTime = System.currentTimeMillis();
Thread th = new Thread(this);
th.start();//start main game
updateTime.start();
}
public void updateGame()
{
//Get the current time
long currentTime = System.currentTimeMillis();
//Calculate how much time has passed since the last update
long elapsedTime = currentTime - lastUpdateTime;
//Store this as the most recent update time
lastUpdateTime = currentTime;
//Create a new dot if enough time has passed
//Update the time since last new dot was drawn
timeSinceLastNewDot += elapsedTime;
if (timeSinceLastNewDot >= NEW_DOT_FREQ)
{
int newX = randomNumber();
int newY = randomNumber();
debugPrint("New dot created at x:" + newX + ", y:" + newY + ".");
BALLS.add(new Ball(newX, newY, 20, 20));
timeSinceLastNewDot = 0;
}
}
private void debugPrint(String value)
{
System.out.println(value);
}
public class updateTime extends Thread implements Runnable
{
public void run()
{
for(t = 0; ; t++)
{
try
{
Thread.sleep(1000);
}
catch(InterruptedException e){}
}
}
}
public int randomNumber()
{
return (int)(Math.random() * 400);
}
public int getRandomColor()
{
return (int)(Math.random() * 6);
}
public class MainBall
{
int x;
int y;
int width;
int height;
int xpos = 100;
int ypos = 100;
int xspeed = 0;
int yspeed = 0;
public MainBall(int x, int y, int width, int height, int xpos, int ypos, int xspeed, int yspeed)
{
this.x = 100;
this.y = 100;
this.width = 10;
this.height = 10;
this.xpos = 100;
this.ypos = 100;
this.xspeed = 0;
this.yspeed = 0;
}
public void paintMainBall(Graphics g)
{
g.setColor(Color.black);
g.fillOval(x, y, width, height);
g.drawString(xpos + ", " + ypos, 20, 40);
}
}//mainBall
class Ball
{
int x;
int y;
int width;
int height;
public Ball(int x, int y, int width, int height)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}//end ball
public void paint(Graphics g)
{
g.setColor(color[getRandomColor()]);
g.fillOval(x, y, width, height);
}//end paint
}//ball class
public void update(Graphics g)//double buffer don't touch!!
{
if(dbImage == null)
{
dbImage = createImage(this.getSize().width, this.getSize().height);
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 boolean keyDown (Event e, int key)
{
if(key == Event.LEFT)
{
mainBall.xspeed = -5;
mainBall.yspeed = 0;
}
if(key == Event.RIGHT)
{
mainBall.xspeed = 5;
mainBall.yspeed = 0;
}
if(key == Event.UP)
{
mainBall.yspeed = -5;
mainBall.xspeed = 0;
}
if(key == Event.DOWN)
{
mainBall.yspeed = 5;
mainBall.xspeed = 0;
}
return true;
}
public void run()
{
while(true)
{
repaint();
if (mainBall.xpos < 1)
{
mainBall.xpos = 449;
}
if (mainBall.xpos > 449)
{
mainBall.xpos = 1;
}
if (mainBall.ypos < 1)
{
mainBall.ypos = 449;
}
if (mainBall.ypos > 449)
{
mainBall.ypos = 1;
}
mainBall.ypos += mainBall.yspeed;
mainBall.xpos += mainBall.xspeed;
try
{
Thread.sleep(20);
}
catch(InterruptedException ex){}
}
}
public void init()
{
this.setSize(WIDTH, HEIGHT);
BALLS = new ArrayList<Ball>();
}
public void paint(Graphics g)
{
g.drawString("time: " + t, 20, 20);
mainBall.paintMainBall(g);
for (Ball ball : BALLS)
{
ball.paint(g);
}
updateGame();
}
}
You update the xPos/yPos values of the ball, but never the x/y values
public void paintMainBall(Graphics g) {
System.out.println("PaintMainBall");
g.setColor(Color.RED);
g.fillOval(x, y, width, height);
g.drawString(xpos + ", " + ypos, 20, 40);
}