I'm trying to make a java sand game and can't get past one bit. i've made my method that draws a rectangle at mouseX and mouseY, and i have set it up so it updates every frame so it constantly follows the mouse.
what i assume is that i would use an array to create each rectangle, and from there would use a pre-defined algorithm to float to the ground, I'm all good with that, i just don't understand how to 'hook my method' up to an array.
This is the method i am using to draw the rectangle (in it's own class called Methods)
import org.newdawn.slick.Graphics;
public class Methods {
public Graphics g = new Graphics();
public int sizeX = 4;
public int sizeY = 4;
public void drawParticle(float x, float y){
g.drawRect(x, y, sizeX, sizeY);
}
}
And this is my main class
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
public class Control extends BasicGameState {
public static final int ID = 1;
public Methods m = new Methods();
int mouseX;
int mouseY;
public void init(GameContainer container, StateBasedGame game) throws SlickException{
}
public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException {
m.drawParticle(mouseX, mouseY);
}
public void update(GameContainer container, StateBasedGame game, int delta) {
}
public void mouseReleased(int button, int x, int y){
mouseX = 0;
mouseY = 0;
}
public void mouseDragged(int oldx, int oldy, int newx, int newy) {
mouseX = newx;
mouseY = newy;
}
public int getID() {
return ID;
}
}
but when i click, just one rectangle follows the mouse, instead of many being created AT the mouse :L
Public Variables:
Rectangle boxes[] = new Rectangle[maxnum];
int boxnum = 0;
On mouse move:
boxes[boxnum] = new Rectangle[e.getX(), e.getY(), sizeX, sizeY);
boxnum = boxnum + 1;
When drawing your particles:
counter = 0;
do
{
g.drawRect(boxes[counter].x, boxes[counter].y, sizeX, sizeY);
counter = counter + 1;
} while (counter < maxnum);
Where maxnum is the maximum number of boxes you will have. This way you can store multiple rectangles in your array and go through the array and draw them when you update the screen. Hope this helps.
Related
I was creating a simple Solar System. The earth rotates around the sun. Now I am struggling while trying to rotate the moon around earth, in the same time while earth rotates around sun.
Thank you for your help!
The earth code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Earth extends JPanel implements ActionListener{
Timer t=new Timer(100,this);
private int x;
private int y;
private int height;
private int width;
private Color color;
double angle;
public Planetet(int x,int y,int height,int width,Color color) {
this.x=x;
this.y=y;
this.height=height;
this.width=width;
this.color=color;}
public void paint(Graphics g) {
//Extra Code for Screen clearing
g.setColor(getBackground());
boolean rotation=true;
int a, b;
if (rotation) {
int width = getWidth();
int height = getHeight();
a = (int) (Math.cos(angle) * (width / 3) + (width / 2));
b = (int) (Math.sin(angle) * (height / 3) + (height / 2));
} else {
a = getWidth()/2 - gjatsia/2;
b = getHeight()/2 - gjersia/2;
}
g.setColor(ngjyra);
g.fillOval(a, b, gjatsia, gjersia);
t.start();
}
public void actionPerformed(ActionEvent e) {
angle+=0.1/2;
if (angle>(2*Math.PI))
angle=0.1;
repaint();}
public static void main (String [] args) {
JFrame MainFrame=new JFrame();
MainFrame.getContentPane().setBackground( Color.black );
MainFrame.setSize(600,600);
Sun sun=new Sun(250,250,50,50,Color.YELLOW);
Earth earth=new Earth(400,270,20,20,Color.blue);
Moon moon=new Moon(400,270,10,10,Color.GRAY);
MainFrame.add(sun);
MainFrame.setVisible(true);
MainFrame.add(earth);
MainFrame.setVisible(true);
MainFrame.add(moon);
MainFrame.setVisible(true);
}
}
The sun code:
import javax.swing.*;
import java.awt.*;
public class Sun extends JComponent{
private int x;
private int y;
private int height;
private int width;
private Color color;
double angle;
public Sun(int x,int y,int height,int width,Color color) {
this.x=x;
this.y=y;
this.height=height;
this.width=width;
this.color=color;}
public void paint(Graphics g) {
g.setColor(color);
g.fillOval(x, y, height, width);
}}
The Moon code (which needs corrections):
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Moon extends JComponent implements ActionListener{
Timer t=new Timer(100,this);
private int x;
private int y;
private int height;
private int width;
private Color color;
double angle;
public Moon(int x,int y,int height,int width,Color color) {
this.x=x;
this.y=y;
this.height=height;
this.width=width;
this.color=color;}
public void paint(Graphics g) {
int width =getWidth();
int height=getHeight();
int a = (int) (Math.cos(angle) * (width/6) + (width/4));
int b = (int) (Math.sin(angle) * (height/6) + (height/4));
g.setColor(ngjyra);
g.fillOval(a, b, gjatsia, gjersia);
t.start();
}
public void actionPerformed(ActionEvent e) {
angle-=0.5/2;
if (angle>(2*Math.PI))
angle=0.0;
repaint();}}
So this is the output. The earth and the moon both rotate on its own
Think about it this way: everything rotates around something - A rotates around B - and B rotates around C - C rotates around D... How can you represent this relationship in code? Perhaps by giving each object a reference to the thing it rotates around...
Also - if you have multiple objects that have the same, or very similar behavior - you can abstract this behavior away to a parent (or abstract) class - which saves you from writing the same code multiple times.
Hope that helps you to think about your code.
I am making a game with a shooter such that when use click it should move left or right but it is made on canvas and onclick listeners didn't work on it so someone told me to get coordinates of canvas and use onclick listeners on it but he don't tell me how to do it
My Code
package --------;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
public class Cannon {
float x = -1; // Cannon's center (x,y)
float y = -1;
float stepX = 40;
int lowerX, lowerY, upperX, upperY;
private Paint paint;
private Context mContext;
// Constructor
public Cannon(int color, Context c) {
paint = new Paint();
paint.setColor(color);
mContext = c;
}
public void setBounds(int lx, int ly, int ux, int uy) {
lowerX = lx;
lowerY = ly;
upperX = ux;
upperY = uy;
x = ux/2;
y = uy;
}
public void moveLeft() {
if (x - 30 > 0) {
x -= stepX;
}
}
public void moveRight() {
if (x + 30 < upperX) {
x += stepX;
}
}
public float getPosition() {
return x;
}
public void draw(Canvas canvas) {
canvas.drawLine(x, y -120, x, y, paint);
canvas.drawRect(x - 90, y - 40, x + 90, y, paint);
}
}
how to use onclick listeners for this rectangle by getting its coordinates to do move left function
You already have a method getPosition, but it only returns the x position.. Create one that returns x and one that returns y, for example:
public float getCannonX(){
return x;
}
public float getCannonY(){
return y;
}
Then in your Activity you can set an onClickListener on your cannon object and access the methods above.
Or you can set an onClickListener on your canvas and use the above methods to check if the cannon coordinates was selected.
You should factor in the size of the cannon object as well
So I am trying to generate random rectangles that the player must avoid. My collision method was working with a single, randomly generated rectangle. I want to draw 10 or so of these and then I will add a finish line and a timer.
Right now, I understand my problem, but I am not sure how to fix it. The ball/player's movement is executed by changing the x or y coordinates by 10 and then repainting the circle. I currently have the rectangles in the same paint method, so each time the player moves the rectangles are regenerated. I would like them to stay in the same place after the initial random generation. I don't really know how to do this though...
Also, if I can get the rectangles to stay in the same place, will my collision method still work with multiple rectangles? or would I need to revise that as well?
I am just going to post the whole program's code because I'm not sure which parts will need to be revised.
import java.awt.*;
import java.awt.Rectangle;
import java.awt.Shape;
import javafx.scene.shape.*;
import java.awt.event.*;
import java.util.Random;
import java.awt.geom.Area;
import javax.swing.JOptionPane;
import java.applet.Applet;
public class Main extends Applet
implements ActionListener{
boolean end = false;
private Rectangle rectangle;
//creates buttons to move player
private Button run = new Button("Run");
private Button jump = new Button("Jump");
private Button fall = new Button("Fall");
//creates player and obstacles
private Circle player = new Circle(110,110,20);
private makeRect block = new makeRect(150, 120, 30, 10);
//initiates the buttons with actionListener
public void init(){
add(run);
add(jump);
add(fall);
run.addActionListener(this);
jump.addActionListener(this);
fall.addActionListener(this);
}
//draws the player and blocks on the screen
public void paint(Graphics g){
for(int numBlocks = 0; numBlocks<11; numBlocks++){
block.draw(g);}
player.draw(g);
}
//if methods to be control movement
public void actionPerformed(ActionEvent e){
if(e.getSource() instanceof Button){
if(e.getSource() == run)
player.horiz(10);
else if (e.getSource()== jump){
player.vert(-10);
}
else if (e.getSource()== fall){
player.down(10);
}
repaint();
collision();
}
}
public void collision(){
if(player.getBounds().intersects(block.getBounds())){
JOptionPane.showMessageDialog(this, "Game Over", "Game Over", JOptionPane.YES_NO_OPTION);
System.exit(ABORT);
end = true;
}
}
class Circle{
private final Color theColor = Color.BLUE;
private int radius;
private int x,y;
public Circle(){
x = 110; y = 110;
radius = 20;
}
public Circle(int x0, int y0, int rad){
x = x0; y = y0; radius = rad;
}
public void draw(Graphics g){
g.fillOval(x - radius, y-radius, 2*radius, 2*radius);
g.setColor(theColor);
}
public void horiz(int val){
for(int c = 0; c<val+1; c++){
x++;
repaint();}
}
public void vert(int val){
y += val;
}
public void down(int val){
y += val;
}
public Rectangle getBounds(){
return new Rectangle(x-radius, y-radius, 2*radius, 2*radius);
}
}
class makeRect{
private int Xmax = 250;
private int Xmin = 140;
private int Wmax = 50;
private int Hmax = 25;
private int Wmin = 10;
private int Hmin = 5;
Random rand = new Random();
private int randx;
private int randh;
private int x, y, width, height;
public makeRect(){
x = 150; y = 120;
width = 30; height = 10;
}
public makeRect(int x0, int y0, int w0, int h0){
x = x0; y = y0; width = w0; height = h0;
}
public void draw(Graphics g) {
int randx = rand.nextInt((Xmax-Xmin)+1)+Xmin;
int randh = rand.nextInt((Hmax-Hmin)+1)+Hmin;
int randw = rand.nextInt((Wmax-Wmin)+1)+Wmin;
g.drawRect(randx, 110+randh, randh, randw);
}
public Rectangle getBounds(){
return new Rectangle(randx, 110+randh, 30, 10);
}
}
}
Thanks!
For that you will need to construct 10 rects (consider using array) first upon initialization, with random postition for each. I mean, postition randomization occurs when the rects are constructed, not when it's drawn.
What you have there is a same rectangle drawn 10 times at different places each time the paint() gets called.
In my game I'm making, I need NPC's/mobs.
I made a class called peasant (my first mob).
In the main class from which the game is running, I have all the information, as well as calling an object called mob1 from Peasant
I need to make it so that if the player is within 300 pixels of the mob, it starts to move towards it. Ive tried doing this but so far, even if the player is 2000 pixels away, the mob starts moving???
Here is my Peasant class
package Entitys.NPCs;
public class Peasant {
public Peasant(float InitX, float InitY, int MobID){
MobX = InitX;
MobY = InitY;
}
//This class shall be used as an object creator. This will randomly move a graphic around, near to a player
private float MobX;
private float MobY;
private int AmountMoved = 0;
private boolean MoveRight = true;
private boolean MoveLeft;
public boolean PlayerDetected = false;
long timer;
//Used to find the mobs X
public float getX(){
return MobX;
}
//Used to find the mobs Y
public float getY(){
return MobY;
}
//Used to set the mobs X
public void setX(float X){
MobX = X;
}
//Used to set the mobs Y
public void setY(float Y){
MobY = Y;
}
//Used to simply move the mob on its X co-ords
public void moveX(int delta){
MobX += delta*0.1f;
}
//Used to simply move the mob on its Y co-ords
public void moveY(int delta){
MobY += delta*0.1f;
}
public void autoEveryThing(int delta, float playerX, float playerY) {
// If the player has not been spotted the NPC/Mob will move left and
// right by 100 Pixels.
if(MobX-300<playerX){
PlayerDetected=true;
}
if(PlayerDetected=true){
if(MobX>playerX){
MobX-=delta*0.12;
}
}
}
}
And here is the main class:
package Worlds.World1;
import org.lwjgl.input.Mouse;
import org.newdawn.slick.Animation;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
import Entitys.NPCs.*;
import Main.SimpleMob;
public class World1A extends BasicGameState{
String mousePosition;
Image world;
Animation player, playerLeft, playerRight;
int[] duration = {200,200};
float playerX;
float playerY;
float WorldX;
float WorldY;
float PlayerVisibleScreenX;
float PlayerVisibleScreenY;
String MovementDirection;
Peasant mob1;
public World1A(int state){
}
public void init(GameContainer gc, StateBasedGame sbg) throws SlickException{
Image [] WalkingLeft = {new Image("res/Sprites/buckysLeft.png"),new Image("res/Sprites/buckysLeft.png")};
Image [] WalkingRight = {new Image("res/Sprites/buckysRight.png"),new Image("res/Sprites/buckysRight.png")};
playerLeft = new Animation(WalkingLeft, duration, false);
playerRight = new Animation(WalkingRight, duration, false);
player = playerRight;
WorldX = 0;
WorldY = 0;
world= new Image("res/WorldImages/WorldBackGround.png");
mousePosition="null";
MovementDirection = "Not Moved Yet";
mob1= new Peasant(2000, 200, 1);
if(WorldX<=0){
playerX = Math.abs(WorldX);
}else{
playerX=0-WorldX;
}
}
public void render(GameContainer gc, StateBasedGame sbg, Graphics g) throws SlickException{
player.draw(450, 300);
if(WorldX>0){
world.draw(0, 0);
g.fillOval(0+mob1.getX(), 0+mob1.getY(), 50, 50);
g.fillRect(0, 0+340, 500, 10);
player.draw(-WorldX + 450, 300);
}else{
world.draw(WorldX, WorldY);
g.fillOval(WorldX+mob1.getX(), WorldY+mob1.getY(), 50, 50);
g.fillRect(WorldX, WorldY+340, 500, 10);
g.fillOval(WorldX+mob1.getX(), WorldY+mob1.getY(), 50, 50);
player.draw(450, 300);
}
g.setColor(Color.white);
//All this is co-ords ect, it is for developement help
g.drawString(String.valueOf(mob1.getX()), 50, 200);
g.drawString("World X: "+ String.valueOf(WorldX), 50, 225);
g.drawString("Player X: "+ String.valueOf(playerX), 50, 250);
g.drawString("Player Detetcted?: "+ String.valueOf(mob1.PlayerDetected), 50, 265);
}
public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException{
if(WorldX<=0){
playerX = Math.abs(WorldX);
}else{
playerX=0-WorldX;
}
mob1.autoEveryThing(delta, playerX, playerY);
int posX = Mouse.getX();
int posY = Mouse.getY();
mousePosition = "X: " + posX + "\nY: " + posY;
Input input = gc.getInput();
if(input.isKeyDown(Input.KEY_LEFT)){
WorldX += delta * 0.1f;
MovementDirection = "Left";
player = playerLeft;
}else if(input.isKeyDown(Input.KEY_RIGHT)){
WorldX -= delta * 0.1f;
MovementDirection = "Right";
player = playerRight;
}else{
MovementDirection = "Not Moving";
}
}
//DO NOT CHANGE
public int getID(){
return 2;
}
}
The autoEveryThing method in the Peasant class should make it so that if(mobX-300
But when I first run this it starts moving towards the player?
even though (2000-300<0) is false, it still sets the PlayerDetected boolean to true???
Why does this happen?
Thanks
EDIT:
After trying to go through thi and fix it I found somthing strange, even if I take out the whole bit which can change PlayerDetected to true, the mob still moves towards the player. This meens that PlayerDetected is becominbg true somwhere, but I cant figure out where?
if(PlayerDetected=true){
is wrong you should use ==
if(PlayerDetected==true){
or even better
boolean isPlayerDetected;
if (isPlayerDetected)
further consider
double dx = mobX - playerX;
double dy = mobY - playerY;
double distance = Math.sqrt(dx*dx + dy*dy);
if (distance < 300) {
// is within distacne threshold
}
so I've been working on getting my boxes to save their position in an array all day and finally thought i came up with something (with a lot of help from you guys) and it just isn't working... can someone please tell me why?
Control class:
import java.awt.Point;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
public class Control extends BasicGameState {
public static final int ID = 1;
public Methods m = new Methods();
public Point[] point = new Point[(800 * 600)];
int pressedX;
int pressedY;
int num = 0;
public void init(GameContainer container, StateBasedGame game) throws SlickException{
}
public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException {
m.drawParticle(pressedX, pressedY);
}
public void update(GameContainer container, StateBasedGame game, int delta) {
}
public void mousePressed(int button, int x, int y) {
pressedX = x;
pressedY = y;
num = num + 1;
point[num].x = pressedX;
point[num].y = pressedY;
}
public int getID() {
return ID;
}
}
Methods class:
import org.newdawn.slick.Graphics;
public class Methods {
public Graphics g = new Graphics();
public int sizeX = 1;
public int sizeY = 1;
public void drawParticle(float x, float y){
g.drawRect(x, y, sizeX, sizeY);
}
}
While you've initialised the size of the point array, you've not initialised the contents.
public void mousePressed(int button, int x, int y) {
pressedX = x;
pressedY = y;
num++;
point[num] = new Point(pressedX, pressedY);
}
Also think in your render method, you need to re-render the graphics (I could be mistaken, I've not used Slick2D before)...
Withing something like...
public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException {
for (Point p : point) {
if (p != null) {
m.drawParticle(p.x, p.y);
}
}
m.drawParticle(pressedX, pressedY);
}
I'm also curious about you creating you're own Graphics, especially when the render method passes you one, you may want to check into that further and make sure that this is acceptable...