I'm trying to make an Agar.io simulation, so I'm using MouseMotionListener's mouseMoved method to find the cursor's location, and calculating the difference between the cursor's coordinates and agar's coordinates to calculate the slope for the animation.
Below is the code for the implemented mouseMoved():
private class CursorTracker implements MouseMotionListener {
public void mouseMoved(MouseEvent e) {
//cursor location
cursor_x = e.getPoint().getX();
cursor_y = e.getPoint().getY();
//agar location
agar_x = agar.getX();
agar_y = agar.getY();
repaint();
}
public void mouseDragged(MouseEvent e) {}
}
Below is actionPerformed() for the panel's timer:
private class Animator implements ActionListener {
public void actionPerformed(ActionEvent e) {
//adding food
if (count == 30) {
addRandomFood();
count = 0;
}
count++;
//agar animation - functions on slope animation: x changes by 1, y by m
double delta_x = cursor_x - agar_x;
double delta_y = cursor_y - agar_y;
//slope
double m = (delta_y)/(delta_x);
//pass parameters
agar.move(1, m);
repaint();
}
}
And here is the code for the Agar.move() method:
public void move(double x_interval, double y_interval) {
if (x >= 0)
x -= x_interval;
if (y >= 0)
y -= y_interval;
}
My intention is to find out the slope (which is ∆y/∆x), change x by 1 and y by the slope (m) value at every timer's repeat, which should theoretically result in the agar object moving towards the cursor location bit by bit. (correct me if I'm wrong)
Also, the cursor detector (mouseMoved) seems to work weirdly; it works only once, agar doesn't change motion direction even the cursor is relocated. And it might even be not properly "listening" to the cursor and just doing it by default because regardless of the cursor's location when the program starts running, the agar always ends up moving along the x-axis towards the origin.
Related
I have a program meant to simulate traffic and all process (movement, drawing new cars, responding to traffic lights) except tracking movement are working.
I have used getter methods
float getXposition(){
return x;
}
float getYposition(){
return y;
}
to determine the location of my sprite but my problem is with conditions relating to the position. For example, my do while loop
do {
topcar.setYvelocity((topcar.getYvelocity()/2));
}while(topcar.getYposition() < 275);
is always bypassed.
Update method(s)
public void update() { // update position and velocity every n milliSec
// default - just move at constant velocity
x += dx; // velocity in x direction
y += dy; // velocity in y direction
}
public void actionPerformed(ActionEvent arg0) {
// called by Timer every 50 milliseconds
for (SimpleSprite s : SimpleSprite.sprites)
s.update(); // update positions of all sprites
repaint();
}
What I wanted to do was make it so that when the light turns red the car sprite should slow down to half speed until it reaches y coordinate 275 and then stop, but instead my sprite will abruptly stop as soon as the light turns red
I am currently working on a 3 cushion billiards game project. I have added two balls on the table so far. I am trying to move one of the balls but I am having a hard time doing that. Should I use a timer? If so then could you tell me an effective way to use the timer on my code so I can move my balls?
Your help would be much appreciated.
Thanks in advance.
Farhan Hasan
I have tried to create a move function for the class balls. But I am not sure what I should put inside the function, I have added the xSpeed and ySpeed. The xLocation and the yLocation changes depending on the xSpeed and ySpeed.
public class Balls
{
private Color ballFillColor;
private Color ballBorderColor;
private int ballX = 0;
private int ballY = 0;
private int xSpeed = 5;
private int ySpeed = 0;
private int ballWidth = 0;
private int ballHeight = 0;
Timer t;
public boolean fillBall = false;
private static Balls ballArray[]; //Required for drawMultipleBalls
Balls(){ //Constructor
ballBorderColor = Color.black;
}
Balls(int ballX, int ballY, int ballWidth, int ballHeight, Color ballBorderColor, JFrame window){ //Constructor
// X , Y , Width, Height, Border Colour, container
this.setBallBorderColor(ballBorderColor);
this.setBallWidth(ballWidth);
this.setBallHeight(ballHeight);
this.setBallX(ballX);
this.setBallY(ballY);
this.drawBall(window);
}
//Here is the move function. I am not really sure what to do here.
public void move()
{
if(this.ballX < 1000 - this.ballWidth)
{
this.ballX += this.xSpeed;
}
try
{
Thread.sleep(1);
}
catch(Exception e)
{
}
}
//GET AND SET FUNCTIONS HERE
//HERE ARE THE FUNCTIONS WHICH ARE RESPONSIBLE FOR DRAWING MY BALLS IN JFRAME
public void drawBall(JFrame frame)
{
frame.getContentPane().add(new MyComponent());
}
public void drawMultipleBalls(JFrame frame, Balls[] balls)
{
ballArray = balls;
frame.getContentPane().add(new MyComponent2());
}
private class MyComponent extends JComponent{
public void paintComponent(Graphics g){
if (fillBall) //Fill first, and then draw outline.
{
g.setColor(ballFillColor);
g.fillOval(getBallX(),getBallY(), getBallHeight(),getBallWidth());
}
g.setColor(getBallBorderColor());
g.drawOval(getBallX(),getBallY(), getBallHeight(),getBallWidth());
}
}
private class MyComponent2 extends JComponent{
public void paintComponent(Graphics g){
for (int i = 0; i < ballArray.length; i++)
{
if (ballArray[i].fillBall) //Fill first, and then draw outline.
{
g.setColor(ballArray[i].ballFillColor);
g.fillOval(ballArray[i].getBallX(),ballArray[i].getBallY(), ballArray[i].getBallHeight(),ballArray[i].getBallWidth());
}
g.setColor(ballArray[i].getBallBorderColor());
g.drawOval(ballArray[i].getBallX(),ballArray[i].getBallY(), ballArray[i].getBallHeight(),ballArray[i].getBallWidth());
}
}
}
Hopefully, I can have two movable balls for the game, the should bounce back as the hit the edge of the screen and they should be able to slow down over time. For that, I am thinking to use a damper (I will multiply the xSpeed and ySpeed with a number less than 1, eventually it will slow down the ball)
Here is a simple example I came up with to show a ball moving and bouncing off the edges.
The direction changes based on the boundary. Left and top edges just check for 0. Bottom and right edges need to include the diameter of the ball.
The x and y increments are independent. And these amounts in conjunction with the timer can change the movement. Notice however, that to have objects bounce off of each other (as in a pool game) is more complicated due to angle of trajectories, etc. And the distances bounced will vary and slow with time based on frictional values. Everything else is documented in the Java API.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MovementDemo extends JPanel implements ActionListener {
JFrame frame = new JFrame("Movement Demo");
int size = 500;
int x = 50;
int y = 200;
int diameter = 50;
int yinc = 2;
int xinc = 2;
int xdirection = 1;
int ydirection = 1;
public MovementDemo() {
setPreferredSize(new Dimension(size, size));
frame.add(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new MovementDemo().start());
}
public void start() {
Timer timer = new Timer(100, this);
timer.setDelay(5);
timer.start();
}
public void actionPerformed(ActionEvent ae) {
if (x < 0) {
xdirection = 1;
}
else if (x > size - diameter) {
xdirection = -1;
}
if (y < 0) {
ydirection = 1;
}
else if (y > size - diameter) {
ydirection = -1;
}
x = x + xdirection * xinc;
y = y + ydirection * yinc;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.BLUE);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillOval(x, y, diameter, diameter);
}
}
It seems in general there are a few things you need to figure out:
has the ball collided with another ball
has the ball collided with a wall
otherwise just figure out what is the ball's new position based on its velocity
Below is some sample code that stubs some of this out. You can first compare the current ball's position to all others (not including the current ball of course). If there are any equal positions, process a collision with a ball. If the ball is at the window border i.e it hit a wall, process a collision with a wall. Otherwise just calculate its new position based on its current velocity.
The process collision part is just to apply physics mechanics to whatever degree of complexity you require. One general suggested change would be to update the velocity of the balls then apply it to the position after. The specific calculations for velocity changes you could apply as needed and as you can imagine it can get pretty involved which is why I suggest using a separate method and possibly a sub class for velocity instead of managing each part of the velocity vector in the ball itself. I used the wall as an object because of this. The composition, weights, velocities etc of the object's colliding can affect the resulting collision, but how complex you want that processing to be is up to you.
Sorry I'm no physics expert but I hope this sends you in the right direction in terms of code! Also this might help with the specific calculations you might want to use:
https://www.khanacademy.org/science/physics/one-dimensional-motion/displacement-velocity-time/v/calculating-average-velocity-or-speed
public void move()
{
// check if balls are on same position not including this ball
for(Ball b: ballArray){
if (this.position == b.position && this != b){
processCollision(this, b, null);
} else{
// if the ball hasn't collided with anything process its movement based on speed
// this assumes a 1000 x 1000 window for keeping objects inside it
if(this.ballX < 1000 - this.ballWidth && this.ballY < 1000 - this.ballHeight){
this.ballX += this.xSpeed;
this.ballY += this.ySpeed;
}else {
processCollision(this, null, new Wall());
}
}
}
try
{
Thread.sleep(1);
}
catch(Exception e)
{
}
}
public void processCollision(Ball b1, Ball b2, Wall w){
// if ball hasn't collided with a wall, process a ball - ball collision
if(w == null){
// apply physics mechanics according the complexity desired for ball collisions
b1.xSpeed -= b2.xSpeed;
b1.ySpeed -= b2.ySpeed;
// ball 2 would end up slowing down
b2.xSpeed -= b1.xSpeed;
b2.ySpeed -= b1.ySpeed;
}
// if ball hasn't collided with a ball, process a ball - wall collision
if(b2 == null){
// apply physics mechanics for hitting a wall
// e.g as below: just send ball in opposite direction
b1.xSpeed = b1.xSpeed * -1;
b1.ySpeed = b1.ySpeed * -1;
}
// either way, process ball's new position based on its new speed
b1.ballX += b1.xSpeed;
b1.ballY += b1.ySpeed;
b2.ballX += b2.xSpeed;
b2.ballY += b2.ySpeed;
}
I am working on a 2D platformer game for my, last, HS year project.
The game is basically about a player walking back & forward, collecting points and reaching goals... The player can shoot bullets and when bullets hit a block, it is destroyed. Now, I wanted to add an explosion effect using so called "particle" objects. I have written the manager class for it and it seemed to have worked the first time but after shooting a few times, i noticed that the particles stopped getting deleted, they just continue and travel out of screen. The life-time limit is 500ns.
I have also noticed that if i shoot bullets as soon as the game starts, the effect finishes as it is supposed to. but after waiting for a few more seconds and then shooting bullets, the effect particles do not behave as they should.
Here is what it looks like when i shoot bullets as soon as i start the game (What it's supposed to look like):
and here is what it looks like, after waiting a few seconds before shooting the bullets.
ParticleManager.java
public class ParticleManager {
private ArrayList<Particle> particles;
private ArrayList<Particle> removeParticles;
public ParticleManager() {
particles = new ArrayList<Particle>();
removeParticles = new ArrayList<Particle>();
}
public int getListSize() {
return particles.size();
}
/*
Generate particles
*/
public void genParticle(int x, int y, int amount) {
for(int i = 0; i < amount; i++) {
particles.add(new Particle("explosion" , x,y, i));
}
}
public void update() {
// Iterate trough particle objects
// update them & check for lifeTime
for(Particle p: particles) {
// Updating particle object before
// checking for time lapse
p.update();
// Append outdated particles to removeParticles
// if time limit has passed
if(System.nanoTime() - p.timePassed >= Config.particleLife) {
removeParticles.add(p);
}
}
// finally, delete all "remove-marked" objects
particles.removeAll(removeParticles);
}
public void render(Graphics2D g) {
for(Particle p: particles) {
p.render(g);
}
}
}
Particle.java
class Particle {
private double px, py, x, y;
private int radius, angle;
public long timePassed;
String type;
public Particle(String type, double x, double y, int angle) {
this.x = x;
this.y = y;
this.radius = 0;
this.angle = angle;
this.timePassed = 0;
this.type = type; // explosion, tail
}
public void update() {
px = x + radius * Math.cos(angle);
py = y + radius * Math.sin(angle);
radius += 2;
this.timePassed = System.nanoTime();
}
public void render(Graphics2D g) {
g.setColor(Color.WHITE);
g.fillOval((int)px, (int)py, 5, 5);
}
}
I haven't figured out what I am doing wrong here, I've googled about some stuff and at one point i came across an answer mentioning that some references don't get deleted directly for some reason...
and my question is "How can I make these particles vanish after a certain amount of time has passed? - as shown in the first GIF"
I think the problem is that you are constantly overwriting timePassed.
// Updating particle object before
// checking for time lapse
p.update();
// Append outdated particles to removeParticles
// if time limit has passed
if(System.nanoTime() - p.timePassed >= Config.particleLife) {
removeParticles.add(p);
}
p.update() sets timePassed to now and then the if check checks if time passed is far from now (it will never be since it was just set).
I think you do want to set timePassed in the constructor (maybe it would be better named timeCreated).
Additionally, just a heads up, you never clear removeParticles so that list is going to grow forever until it causes the process to run out of memory.
I am making a game which needs an "arrow" to be shot from a stationary location (a set coordinate). The arrow's trajectory is based on the location that the user Clicks in the GUI. This is essentially an Aiming feature. I cant get the arrow to follow a working path, any equations ie used have led to weird, glitchy, and buggy results.
public class ReShoot implements ActionListener
{
public void actionPerformed(ActionEvent e){
ArrowShoot shoot = new ArrowShoot();
shoot.ReShoot();
}
}
public class ArrowShoot implements ActionListener
{
public Timer T = new Timer(5, this);
Arrow A = new Arrow();
public void ReShoot(){
T.start();
arrow_x=0;
arrow_y=200;
A.setBounds(0,200,10,10);
}
// MAIN: y=-16t^2 + Vy * t + h
//Vy = v * sin(a)
//Vx = v * cos(a)
//a = arctan( (200-mouse_y)/v
//v = Mouse_x - Arrow_x
//t = x / Vx
public void actionPerformed(ActionEvent e)
{//arrow_y = 0.0025 * Math.pow((mouse_x-arrow_x), 2)+ mouse_y;
Container container_arrow = getContentPane();
container_arrow.setLayout(null);
container_arrow.add(A);
A.setBounds(0,200,10,10);
arrow_x++;
double v = mouse_x/2; //height change
double a = 50* Math.atan((200-mouse_y) / (v));
double Vy = v * Math.sin(a);
double Vx = v * Math.cos(a);
double t = arrow_x/Vx;
double h = 200;
arrow_y = (16) * Math.pow(t, 2) + (Vy * t) + h;
int x = (int)Math.round(arrow_x);
int y = (int)Math.round(arrow_y);
A.setBounds(x, y,10,10);
if (arrow_y>=500)
T.stop();
}
I am pretty sure im doing this all wrong, and there has to be a more effective method to accomplish this task.
It doesn't look like you are calculating the trajectory path correctly. In actionPerformed, you are incrementing the x coordinate of the arrow, and then calculating the corresponding y. This will not work at all, since even though you can calculate y as a function of x, x is itself a function of t (time). Hence you have to calculate x at time t instead of assuming that x will always increase by 1 at the next invocation.
Given that you can calculate the angle, you can calculate the position of x and y as a function of time and the angle using the following formulas:
So your algorithm will essentially be:
time++; //time variable that you maintain
arrow_x = ... //calculate using (1)
arrow_y = ... //calculate using (2)
I want to be able to create new particles from wherever I click on stage. I'm just stuck on adding the mouse portion and I've tried to add/pass parameters and I always get errors while I try setting the parameters. Any suggestions?
This is my current code:
float parSpeed = 1; //speed of particles
int nParticles = 1000; //# of particles
Particle[] particles;
void setup() {
size(700,700); //size of image (8.5 x 11 # 300px) is 3300,2550)
frameRate(60); //framerate of stage
background(0); //color of background
particles = new Particle[nParticles];
//start particle array
for(int i=0; i<nParticles; i++) {
particles[i] = new Particle();
}
}
void draw() {
fill(0,0,0,5); //5 is Alpha
rect(0,0,width,height); //color of rectangle on top?
translate(width/2, height/2); //starting point of particles
//start particle array
for(int i=0; i<nParticles; i++) {
particles[i].update();
particles[i].show();
}
}
//Particle Class
class Particle {
PVector pos; //position
float angle; //angle
float dRange; //diameter range
float dAngle; //beginning angle?
color c; //color
Particle() {
pos = new PVector(0,0);//new position for the particles.
angle = 1; //controls randomization of direction in position when multiplied
dRange = 0.01; // how big of a circle shold the particles rotate on
dAngle = 0.15; // -- maximum angle when starting
c = color(0,0,random(100, 255)); //set color to random blue
}
void update() {
float cor = .25*dRange*atan(angle)/PI;
float randNum = (random(2)-1)*dRange-cor; //Random number from (-dRange, dRange)
dAngle+=randNum; //We don't change the angle directly
//but its differential - source of the smoothness!
angle+=dAngle; //new angle is angle+dAngle -- change angle each frame
pos.x+=parSpeed*cos(angle);//random direction for X axis multiplied by speed
pos.y+=parSpeed*sin(angle);//rabdin durectuib for y axis multiplied by speed
}
void show() {
fill(c); //fill in the random color
noStroke(); //no stroke
ellipse(pos.x,pos.y,10,10); //make the shape
smooth(); //smooth out the animation
}
}
void keyPressed() {
print("pressed " + int(key) + " " + keyCode);
if (key == 's' || key == 'S'){
saveFrame("image-##.png");
}
}
void mouseReleased() {
print("mouse has been clicked!");
}
Overwrite the mouseReleased() method:
In there you'll need to:
capture the position of the mouse
create the new particle
update the position of the newly created particle.
add it to the array (the particle system)
This may look simple but you'll have to keep in mind an array cannot change sizes. I would advise that you create a ParticleSystem class that takes care of adding and removing particles from the system.
Edit: You might want to consider using an ArrayList instead of an Array of Particles. Have a look at this
In pseudo code this would look like this:
void mouseReleased() {
int particleX = mouseX;
int particleY = mouseY;
Particle P = new Particle();
P.setPos ( new PVector ( particleX, particleY ) ); // this needs to be implemented
ParticleSystem.add ( P ); // this needs to be implemented
}
I hope this will be a good start.
AH