public class AsteroidMovement : MonoBehaviour
{
public Vector2 speed;
public Vector2 direction;
private Vector2 movement;
private Vector3 TopScreenBound;
private Vector3 BottomScreenBound;
// Use this for initialization
void Start()
{
TopScreenBound = Camera.main.ViewportToWorldPoint(new Vector3(0f, 1f, 0f));
BottomScreenBound = Camera.main.ViewportToWorldPoint(new Vector3(0f, 0f, 0f));
}
// Update is called once per frame
void Update()
{
if (gameObject.transform.position.y >= TopScreenBound.y)
{
direction.y *= -1;
}
if (gameObject.transform.position.y <= BottomScreenBound.y)
{
direction.y *= -1;
}
movement = new Vector2(speed.x * direction.x, speed.y * direction.y);
}
void FixedUpdate()
{
rigidbody2D.velocity = movement;
}
}
I am trying to have asteroids in my game bounce off the edge of my screen and I have got it working decently, but after a few bounces, the asteroid/object gets "stuck" in the wall and glitches out the playing area.
Am I going about this wrong? I cannot see where in the code its making the asteroids stuck after a couple of bounces.Thanks in advance :)
You must fix your object's position to bounce inside the screen, if your object is already outside of the screen and it does not fully enter in screen space in the next frame, then your object is changing it's direction infinitely until it enters or leaves the screen.
Change this:
if (gameObject.transform.position.y >= TopScreenBound.y)
{
direction.y *= -1;
}
if (gameObject.transform.position.y <= BottomScreenBound.y)
{
direction.y *= -1;
}
To this:
if (gameObject.transform.position.y >= TopScreenBound.y)
{
gameObject.transform.position.y = TopScreenBound.y;
direction.y *= -1;
}
if (gameObject.transform.position.y <= BottomScreenBound.y)
{
gameObject.transform.position.y = BottomScreenBound.y;
direction.y *= -1;
}
Related
i want to achieve like this:
enter image description here
here is my code:
class Particle {
PVector position;
PVector velocity;
PVector acceleration;
PVector initialVelocity;
ArrayList<PVector> path;
boolean life = true;
float q;
public Particle(PVector position, PVector initialVelocity) {
this.position = position;
this.acceleration = new PVector(0, 0);
this.initialVelocity = initialVelocity;
this.velocity = new PVector(0, 0);
path = new ArrayList<PVector>();
}
public void run() {
update();
display();
}
private void update() {
velocity.add(acceleration);
velocity.limit(maxspeed);
trail.add(position.copy());
position.add(velocity);
occurOtherCurves();
arriveBorders();
path.add(position.copy());
acceleration.mult(0);
}
private void display() {
beginShape();
stroke(0);
strokeWeight(1);
noFill();
for(PVector v : path) {
vertex(v.x, v.y);
}
}
public void followField(Field field) {
PVector desired = field.lookup(initialVelocity);
desired.mult(maxspeed);
PVector steer = PVector.sub(desired, velocity);
steer.limit(maxforce);
applyForce(steer);
}
private void applyForce(PVector force) {
acceleration.add(force);
}
public boolean isEndMove(){
return !life;
}
private void arriveBorders(){
if(position.x <= 0 || position.x >= width || position.y <= 0 || position.y >= height)
life = false;
}
private void occurOtherCurves() {
for(PVector p : trail) {
if(p.x == position.x && p.y == position.y) life = false;
}
}
public ArrayList<PVector> getPath() {
return path;
}
}
in occurOtherCurves() function ,ArrayList<PVector> trail is a global variable used to record the positions that all particles passed through,but it didn't work.
thanks for you help.
Stack Overflow isn't really designed for general "how do I do this" type questions. It's for more specific "I tried X, expected Y, but got Z instead" type questions.
But generally, it sounds like what you'd want to do is check whether a new path segment intersects with any existing path segments. If it does, then truncate it at the intersection point (or just don't add it) and stop adding path segments to that path.
You'll have much better luck if you break your problem down into smaller pieces, and take on one piece at a time. Then if you get stuck, you can post a MCVE along with a specific technical question. Good luck.
Im trying to create a basic pool game where one ball hits another and causes that second ball to continue in the same direction at the same speed and move the same amount of distance that the first ball moved. I've so far gotten everything to work except having that second ball continue on. Would anyone be able to help me make this work? I think my problem lies in click == 4 section of the code, but I don't understand how to fix it/add on to it.
Ball cue, billiard;
boolean fired = false;
String msg;
int click;
int steps = 20;
int difx, dify;
Boolean move = false;
void setup(){
msg = "";
size(600,300);
click = 0;
cue = new Ball(30, #FFFFFF);
billiard = new Ball(30, #000000);
}
void draw(){
background(#009900);
if(click == 0){
cue.xpos = mouseX;
cue.ypos = mouseY;
billiard.xpos = -15;
billiard.ypos = -15;
msg = "please place the cue ball";
}else if(click == 1){
billiard.xpos = mouseX;
billiard.ypos = mouseY;
msg = "click again to place billiard ball";
}else if(click ==2){
difx = cue.xpos-billiard.xpos;
dify = cue.ypos-billiard.ypos;
}else if(click == 3){
float cdistance = dist(cue.xpos,cue.ypos,billiard.xpos,billiard.ypos);
if(cdistance>billiard.ballDiam/2){
move = true;
cue.xpos-=difx/steps;
cue.ypos-=dify/steps;
msg = "You got it! Push c on your keyboard to restart";
}else{
move = false;
cue.visible = true;
click = 4;
}
}else if(click == 4){
float cdistance = dist(cue.xpos,cue.ypos,billiard.xpos,billiard.ypos);
if(cdistance<billiard.ballDiam){
if (dist(cue.xpos, cue.ypos, billiard.xpos, billiard.ypos) < sqrt(sq(difx)+sq(dify))) {
move = true;
billiard.xpos-=difx/steps;
billiard.ypos-=difx/steps;
}
}
}
cue.update();
billiard.update();
textSize(20);
text(msg,0,height-5);
}
void mouseClicked(){
if(!move){
click++;
}
}
class Ball{
int xpos, ypos;
int ballDiam;
color myColor;
boolean visible = true;
Ball(int tempdiam,color tempColor){
ballDiam=tempdiam;
myColor=tempColor;
}
void update(){
if(visible){
fill(myColor);
ellipse(xpos,ypos,ballDiam,ballDiam);
}
}
}
Your first stop should be the examples that come with Processing, specifically the CircleCollision example inside the Motion section. That example includes all of the logic for bouncing balls off of one another using more-or-less realistic physics.
/**
* Circle Collision with Swapping Velocities
* by Ira Greenberg.
*
* Based on Keith Peter's Solution in
* Foundation Actionscript Animation: Making Things Move!
*/
Ball[] balls = {
new Ball(100, 400, 20),
new Ball(700, 400, 80)
};
void setup() {
size(640, 360);
}
void draw() {
background(51);
for (Ball b : balls) {
b.update();
b.display();
b.checkBoundaryCollision();
}
balls[0].checkCollision(balls[1]);
}
class Ball {
PVector position;
PVector velocity;
float r, m;
Ball(float x, float y, float r_) {
position = new PVector(x, y);
velocity = PVector.random2D();
velocity.mult(3);
r = r_;
m = r*.1;
}
void update() {
position.add(velocity);
}
void checkBoundaryCollision() {
if (position.x > width-r) {
position.x = width-r;
velocity.x *= -1;
}
else if (position.x < r) {
position.x = r;
velocity.x *= -1;
}
else if (position.y > height-r) {
position.y = height-r;
velocity.y *= -1;
}
else if (position.y < r) {
position.y = r;
velocity.y *= -1;
}
}
void checkCollision(Ball other) {
// get distances between the balls components
PVector bVect = PVector.sub(other.position, position);
// calculate magnitude of the vector separating the balls
float bVectMag = bVect.mag();
if (bVectMag < r + other.r) {
// get angle of bVect
float theta = bVect.heading();
// precalculate trig values
float sine = sin(theta);
float cosine = cos(theta);
/* bTemp will hold rotated ball positions. You
just need to worry about bTemp[1] position*/
PVector[] bTemp = {
new PVector(), new PVector()
};
/* this ball's position is relative to the other
so you can use the vector between them (bVect) as the
reference point in the rotation expressions.
bTemp[0].position.x and bTemp[0].position.y will initialize
automatically to 0.0, which is what you want
since b[1] will rotate around b[0] */
bTemp[1].x = cosine * bVect.x + sine * bVect.y;
bTemp[1].y = cosine * bVect.y - sine * bVect.x;
// rotate Temporary velocities
PVector[] vTemp = {
new PVector(), new PVector()
};
vTemp[0].x = cosine * velocity.x + sine * velocity.y;
vTemp[0].y = cosine * velocity.y - sine * velocity.x;
vTemp[1].x = cosine * other.velocity.x + sine * other.velocity.y;
vTemp[1].y = cosine * other.velocity.y - sine * other.velocity.x;
/* Now that velocities are rotated, you can use 1D
conservation of momentum equations to calculate
the final velocity along the x-axis. */
PVector[] vFinal = {
new PVector(), new PVector()
};
// final rotated velocity for b[0]
vFinal[0].x = ((m - other.m) * vTemp[0].x + 2 * other.m * vTemp[1].x) / (m + other.m);
vFinal[0].y = vTemp[0].y;
// final rotated velocity for b[0]
vFinal[1].x = ((other.m - m) * vTemp[1].x + 2 * m * vTemp[0].x) / (m + other.m);
vFinal[1].y = vTemp[1].y;
// hack to avoid clumping
bTemp[0].x += vFinal[0].x;
bTemp[1].x += vFinal[1].x;
/* Rotate ball positions and velocities back
Reverse signs in trig expressions to rotate
in the opposite direction */
// rotate balls
PVector[] bFinal = {
new PVector(), new PVector()
};
bFinal[0].x = cosine * bTemp[0].x - sine * bTemp[0].y;
bFinal[0].y = cosine * bTemp[0].y + sine * bTemp[0].x;
bFinal[1].x = cosine * bTemp[1].x - sine * bTemp[1].y;
bFinal[1].y = cosine * bTemp[1].y + sine * bTemp[1].x;
// update balls to screen position
other.position.x = position.x + bFinal[1].x;
other.position.y = position.y + bFinal[1].y;
position.add(bFinal[0]);
// update velocities
velocity.x = cosine * vFinal[0].x - sine * vFinal[0].y;
velocity.y = cosine * vFinal[0].y + sine * vFinal[0].x;
other.velocity.x = cosine * vFinal[1].x - sine * vFinal[1].y;
other.velocity.y = cosine * vFinal[1].y + sine * vFinal[1].x;
}
}
void display() {
noStroke();
fill(204);
ellipse(position.x, position.y, r*2, r*2);
}
}
Here's your solution (but you have to re-design your program too):
Ball cue, billiard;
boolean fired = false;
String msg;
int click;
int steps = 20;
int difx, dify;
Boolean move = false;
Boolean continueMoving;
void setup() {
msg = "";
size(600, 300);
click = 0;
cue = new Ball(30, #FFFFFF);
billiard = new Ball(30, #000000);
continueMoving = false;
}
void draw() {
background(#009900);
if (click == 0) {
cue.xpos = mouseX;
cue.ypos = mouseY;
billiard.xpos = -15;
billiard.ypos = -15;
msg = "please place the cue ball";
}
else if (click == 1) {
billiard.xpos = mouseX;
billiard.ypos = mouseY;
msg = "click again to place billiard ball";
}
else if (click ==2) {
difx = cue.xpos-billiard.xpos;
dify = cue.ypos-billiard.ypos;
}
else if (click == 3) {
float cdistance = dist(cue.xpos, cue.ypos, billiard.xpos, billiard.ypos);
if (cdistance>billiard.ballDiam/2) {
move = true;
cue.xpos-=difx/steps;
cue.ypos-=dify/steps;
msg = "You got it! Push c on your keyboard to restart";
}
else {
move = false;
cue.visible = true;
click = 4;
}
}
else if (click == 4)
{
float cdistance = dist(cue.xpos, cue.ypos, billiard.xpos, billiard.ypos);
if (cdistance<billiard.ballDiam)
{
if (dist(cue.xpos, cue.ypos, billiard.xpos, billiard.ypos) < sqrt(sq(difx)+sq(dify))) {
move = true;
continueMoving = true;
billiard.xpos-=difx/steps;
billiard.ypos-=dify/steps;
//print(click);
}
}
}
if (continueMoving)
{
billiard.xpos-=difx/steps;
billiard.ypos-=dify/steps;
}
cue.update();
billiard.update();
textSize(20);
text(msg, 0, height-5);
print(click);
}//draw
void mouseClicked() {
if (!move) {
click++;
}
}
class Ball
{
int xpos, ypos;
int ballDiam;
color myColor;
boolean visible = true;
Ball(int tempdiam, color tempColor) {
ballDiam=tempdiam;
myColor=tempColor;
}
void update() {
if (visible) {
fill(myColor);
ellipse(xpos, ypos, ballDiam, ballDiam);
}
}
}//Ball class
First, instead of using if else statements, use switch. Second, don't put all your code in the draw function. You can put your switch statements there, but shift the code within the conditions to some functions outside the draw function. Google for how other people have created snooker/billiards games, and you'll get to know other different types of logic. Mostly, they will be using a for or while loop to keep the game going. And that loop will be the same as your draw function.
If you're new to StackOverflow, you can click the arrow button pointing up on this page to give me a few points for this answer, and click the tick mark to mark this as the accepted answer.
I am trying to draw a number of shapes in processing which react to each others movements. So when I move one of them, it is connected to say 1 or 2 of the other shapes in the sketch. However I don't want it to be a static movement, I want it to look quite natural.
The only code I have at the moment is basic drawing of a shape which moves when you drag it, but have no idea how to link shapes :( Help!!
float bx;
float by;
int boxSize = 75;
boolean overBox = false;
boolean locked = false;
float xOffset = 0.0;
float yOffset = 0.0;
void setup()
{
size(640, 360);
bx = width/2.0;
by = height/2.0;
rectMode(RADIUS);
}
void draw()
{
background(0);
// Test if the cursor is over the box
if (mouseX > bx-boxSize && mouseX < bx+boxSize &&
mouseY > by-boxSize && mouseY < by+boxSize) {
overBox = true;
}
// Draw the box
rect(bx, by, boxSize, boxSize);
}
void mousePressed() {
if(overBox) {
locked = true;
} else {
locked = false;
}
xOffset = mouseX-bx;
yOffset = mouseY-by;
}
void mouseDragged() {
if(locked) {
bx = mouseX-xOffset;
by = mouseY-yOffset;
}
}
void mouseReleased() {
locked = false;
}
I am thinking I need to use PShape, but am unsure.
First of all, I recommend you to use a class for the shapes, that way you can link them easily.
I make some changes in your code in order to get some kind of following behaviour.
class Box{
float bx;
float by;
int size = 75;
Box(float bx, float by){
this.bx = bx;
this.by = by;
}
void drawBox(){
rect(bx, by, size, size);
}
void moveBox(float x, float y){
bx = bx + x;
by = by + y;
}
}
boolean overBox = false;
boolean locked = false;
float xOffset = 0.0;
float yOffset = 0.0;
Box box, secondBox, thirdBox;
void setup()
{
size(640, 360);
box = new Box(width/2.0, height/2.0);
secondBox = new Box(100, 100);
thirdBox = new Box(500, 300);
rectMode(RADIUS);
}
void draw()
{
background(0);
// Test if the cursor is over the box
if (mouseX > box.bx-box.size && mouseX < box.bx+box.size &&
mouseY > box.by-box.size && mouseY < box.by+box.size) {
overBox = true;
box.drawBox();
secondBox.drawBox();
thirdBox.drawBox();
}
}
void mousePressed() {
if(overBox) {
locked = true;
} else {
locked = false;
}
xOffset = mouseX-box.bx;
yOffset = mouseY-box.by;
}
void mouseDragged() {
if(locked) {
box.bx = mouseX-xOffset;
box.by = mouseY-yOffset;
deltaMovemente(box, secondBox);
deltaMovemente(box, thirdBox);
}
}
void mouseReleased() {
locked = false;
}
void deltaMovemente(Box follow, Box box){
float dx = (follow.bx - box.bx)/50;
float dy = (follow.by - box.by)/50;
box.moveBox(dx, dy);
}
Hope this can be useful.
Regards.
So, I'm working on a processing project that lets me use an image as a cursor but I've been having problems with the cursor image because it has been constantly blinking. I read that if the cursor image is too big it has a tendency to constantly blink. However, I was wondering if there was any way that I could keep the size of my image, while still maintaining it as a cursor. OR,
I was wondering if there was a code that lets me press the image and drag it around the screen. :/
Here's the code that I've been using.
// Declaring a variable of type PImage
PImage img;
PImage img2;
void setup() {
size(815,514);
// Make a new instance of a PImage by loading an image file
img = loadImage("preamble.jpg");
img2 = loadImage("blackgun.png");
}
void draw() {
background(0);
// Draw the image to the screen at coordinate (0,0)
image(img,0,0);
//using the image as the cursor
if (mouseX < 50) {
cursor(img2);
} else {
cursor(img2);
}
}
In the reference they say: "it is recommended to make the size 16x16 or 32x32 pixels" about the image to be used as cursor. You can do this by calling resize:
img2 = loadImage("blackgun.png");
img2.resize(32,32);
Also there is no point in the lines:
if (mouseX < 50) {
cursor(img2);
} else {
cursor(img2);
}
As either way you end up with the same img2 as cursor image.
YOu can just use:
image(img, mouseX, mouseY);
but the cursor will be over the image.
That's a simple and poor drag...
I have here an old example of a little better drag and drop, it is using rects() intead of images but the idea is the same and you can easily adapt it to use images:
DragMe[] drags = new DragMe[40];
void setup() {
size(400, 400);
for (int i = 0; i < drags.length; i++) {
drags[i] = new DragMe();
}
}
void draw() {
background(255);
for (int i = 0; i < drags.length; i++) {
drags[i].display();
drags[i].update();
}
}
void mousePressed() {
for (int i = 0; i < drags.length; i++) {
if (!drags[i].isOver())
drags[i].dontMove = true;
drags[i].offset_x = mouseX - drags[i].pos_x;
drags[i].offset_y = mouseY - drags[i].pos_y;
}
}
void mouseReleased() {
for (int i = 0; i < drags.length; i++) {
drags[i].locked = false;
drags[i].dontMove = false;
}
}
class DragMe {
float pos_x, pos_y, SIZE = 20;
float prev_x, prev_y;
boolean locked;
boolean dontMove;
color c = color (0, 170, 170);
float offset_x, offset_y;
DragMe() {
pos_x = random(width-SIZE);
pos_y = random(height-SIZE);
}
void update() {
if (isOver() && !locked && !dontMove || locked && !dontMove )
c = color (170);
else
c = color (0, 170, 170);
if (isClicked()) {
locked = true;
}
if (locked && !dontMove) {
pos_x = mouseX - offset_x;
pos_y = mouseY - offset_y;
}
}
void display() {
fill(c);
rect(pos_x, pos_y, SIZE, SIZE);
}
boolean isOver() {
float right_x = pos_x + SIZE;
float bottom_y = pos_y + SIZE;
return mouseX >= pos_x && mouseX <= right_x &&
mouseY >= pos_y && mouseY <= bottom_y;
}
boolean isClicked() {
return isOver() && mousePressed && !dontMove;
}
}
I basically want a character to walk in one direction for a while, stop, then go in another random direction. Right now my sprites look but don't move, randomly very quickly in all directions then wait and have another seizure. I will post the code I have so far in case that is useful.
class NPC: Mover
{
int movementTimer = 0;
public override Vector2 direction
{
get
{
Random rand = new Random();
int randDirection = rand.Next(8);
Vector2 inputDirection = Vector2.Zero;
if (movementTimer >= 50)
{
if (randDirection == 4)
{
inputDirection.X -= 1;
movingLeft = true;
}
else movingLeft = false;
if (randDirection == 1)
{
inputDirection.X += 1;
movingRight = true;
}
else movingRight = false;
if (randDirection == 2)
{
inputDirection.Y -= 1;
movingUp = true;
}
else movingUp = false;
if (randDirection == 3)
{
inputDirection.Y += 25;
movingDown = true;
}
else movingDown = false;
if (movementTimer >= 100)
{
movementTimer = 0;
}
}
return inputDirection * speed;
}
}
public NPC(Texture2D textureImage, Vector2 position,
Point frameSize, int collisionOffset, Point currentFrame, Point sheetSize,
Vector2 speed)
: base(textureImage, position, frameSize, collisionOffset, currentFrame,
sheetSize, speed)
{
}
public NPC(Texture2D textureImage, Vector2 position,
Point frameSize, int collisionOffset, Point currentFrame, Point sheetSize,
Vector2 speed, int millisecondsPerframe)
: base(textureImage, position, frameSize, collisionOffset, currentFrame,
sheetSize, speed, millisecondsPerframe)
{
}
public override void Update(GameTime gameTime, Rectangle clientBounds)
{
movementTimer++;
position += direction;
if (position.X < 0)
position.X = 0;
if (position.Y < 0)
position.Y = 0;
if (position.X > clientBounds.Width - frameSize.X)
position.X = clientBounds.Width - frameSize.X;
if (position.Y > clientBounds.Height - frameSize.Y)
position.Y = clientBounds.Height - frameSize.Y;
base.Update(gameTime, clientBounds);
}
}
How about you create a method to get a random direction:
Vector2 GetRandomDirection()
{
Random random = new Random();
int randomDirection = random.Next(8);
switch (randomDirection)
{
case 1:
return new Vector2(-1, 0);
case 2:
return new Vector2(1, 0);
case 3:
return new Vector2(0, -1);
case 4:
return new Vector2(0, 1);
//plus perhaps additional directions?
default:
return Vector2.Zero;
}
}
And then, when a set time has elapsed, you call that method to change the direction:
double totalElapsedSeconds = 0;
const double MovementChangeTimeSeconds = 2.0; //seconds
public override void Update(GameTime gameTime, Rectangle clientBounds)
{
totalElapsedSeconds += gameTime.ElapsedGameTime.TotalSeconds;
if (totalElapsedSeconds >= MovementChangeTimeSeconds)
{
totalElapsedSeconds -= MovementChangeTimeSeconds;
this.direction = GetRandomDirection();
}
position += direction;
//...
}
Use different code to detect which direction the NPC is moving (the booleans movingLeft, movingRight, etc.). Detect those values based on the direction vector. This way you don't have to assign redundant values.
enum MoveDirection
{
Up, Down, Left, Right, UpLeft, UpRight, DownLeft, DownRight, None
}
public MoveDirection GetMoveDirection(Vector2 direction)
{
if (direction.Y < 0)
{
if (direction.X < 0)
return MoveDirection.UpLeft;
else if (direction.X > 0)
return MoveDirection.UpRight;
else
return MoveDirection.Up;
}
else if (direction.Y > 0)
{
if (direction.X < 0)
return MoveDirection.DownLeft;
else if (direction.X > 0)
return MoveDirection.DownRight;
else
return MoveDirection.Down;
}
else
{
if (direction.X < 0)
return MoveDirection.Left;
else if (direction.X > 0)
return MoveDirection.Right;
else
return MoveDirection.None;
}
}
I presume this is used for rotating the sprite (or perhaps drawing a different one), so now you just need a switch:
public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
{
MoveDirection moveDirection = GetMoveDirection(this.direction);
switch(moveDirection)
{
case MoveDirection.Up:
//Draw up-facing sprite, or assign a value to a rotation variable.
break;
case MoveDirection.UpLeft:
//...
}
}
You can examine Platformer Starter Kit to know how enemies move.
As Microsoft discontinue the XNA development for Windows 8, he removes all links to download XNA 4 starter kits.
I upload original Platformer source code to bitbucket.
Here you can download original Platformer Starter Kit Source Code for XNA 4 http://vackup.blogspot.com.ar/2012/11/download-original-platformer-starter.html