Most learned friends
I have a sprite that moves around on screen but at the moment it just moves diagonally from left to right and goes off screen and then comes back on the other side.
What I would like it to do is bounce off the edges of the screen in a random fashion but, not being all that clued up on maths, I'm struggling to figure out the coordinates to do this.
Below is what I have so far: (this is an updated code for the Sprite class:
public class Sprite {
//x,y position of sprite - initial position (0,50)
// int [] DIRECTION_TO_ANIMATION_MAP = {3, 1, 0, 2};
private static final int BMP_ROWS = 3;
private static final int BMP_COLUMNS = 4;
private int x = 0;
private int y = 0;
private int xSpeed = 5;//Horizontal increment of position (speed)
private int ySpeed;// Vertical increment of position (speed)
private int currentFrame = 0;
private GameView gameView;
private Bitmap spritebmp;
//Width and Height of the Sprite image
private int bmp_width;
private int bmp_height;
// Needed for new random coordinates.
//private Random random = new Random();
public Sprite(GameView gameView) {
this.gameView = gameView;
spritebmp = BitmapFactory.decodeResource(gameView.getResources(),
R.drawable.running_ninja_sprite);
this.bmp_width = spritebmp.getWidth() / BMP_COLUMNS;
this.bmp_height = spritebmp.getHeight() / BMP_ROWS;
/*Random rnd = new Random(System.currentTimeMillis());
xSpeed = rnd.nextInt(45)-5;
ySpeed = rnd.nextInt(25)-5;*/
}
//update the position of the sprite
public void update() {
//if (x < 0 || x > gameView.getWidth() ){ xSpeed = xSpeed * -1;}
//if (y < 0 || y > gameView.getHeight() ){ ySpeed = ySpeed * -1;}
if (x > gameView.getWidth() - bmp_width - xSpeed || x + xSpeed < 0) {
xSpeed = -xSpeed;
}
x = x + xSpeed;
if (y > gameView.getHeight() - bmp_height - ySpeed || y + ySpeed < 0) {
ySpeed = -ySpeed;
}
y = y + xSpeed;
currentFrame = ++currentFrame % BMP_COLUMNS;
//y = random.nextInt(gameView.getWidth());
//wrapAround(); //Adjust motion of sprite.
}
public void draw(Canvas canvas) {
update();
int srcX = currentFrame * bmp_width;
int srcY = 1 * bmp_height; //getAnimationRow()
Rect src = new Rect(srcX, srcY, srcX + bmp_width, srcY + bmp_height);
Rect dst = new Rect(x, y, x + bmp_width, y + bmp_height);
//Draw sprite image
canvas.drawBitmap(spritebmp, x, y, null);
}
/*private int getAnimationRow() {
double dirDouble = (Math.atan2(xSpeed, ySpeed) / (Math.PI / 2) + 2);
int direction = (int) Math.round(dirDouble) % BMP_ROWS;
return DIRECTION_TO_ANIMATION_MAP[direction];
}*/
public void wrapAround() {
//Code to wrap around
if (x < 0) x = x + gameView.getWidth(); //increment x whilst not off screen
if (x >= gameView.getWidth()) { //if gone of the right sides of screen
x = x - gameView.getWidth(); //Reset x
}
if (y < 0) y = y + gameView.getHeight();//increment y whilst not off screen
if (y >= gameView.getHeight()) {//if gone of the bottom of screen
y -= gameView.getHeight();//Reset y
}
}
// Checks if the sprite was touched
public boolean wasItTouched(float ex, float ey) {
boolean touched = false;
if ((x <= ex) && (ex < x + bmp_width) &&
(y <= ey) && (ey < y + bmp_height)) {
touched = true;
}
return touched;
}
}
It now does bounce off the edge but from top left, diagonally to the right and back up in the same direction and continues to do this back and forth. I'd like it to be random in its direction after hitting the edge. Any suggestions? As you can see from the code I have tried a lot of things but the sprite just keeps on doing this continuous back and forth diagonal motion and I'm at a loss as to what I can do.
Thanks
Just negate your speed every time you hit a wall
if (x < 0 || x > gameView.getWidth() ){ xSpeed = xSpeed * -1;}
if (y < 0 || y > gameView.getHeight() ){ ySpeed = ySpeed * -1;}
/////////////////////////////// Edit
It will fit something like this. You can also remove your wrap function as it is no longer applicable
//update the position of the sprite
public void update() {
x = x + xSpeed;
y = y + xSpeed;
bounce();
}
private void bounce(){
if (x <= 0 || x >= gameView.getWidth() ){ xSpeed = xSpeed * -1;}
if (y <= 0 || y >= gameView.getHeight() ){ ySpeed = ySpeed * -1;}
}
Related
I am trying to make a processing program, but if I use P2D, P3D, or OPENGL mode I get an error:
com.sun.jdi.VMDisconnectedException
at com.sun.tools.jdi.TargetVM.waitForReply(TargetVM.java:285)
at com.sun.tools.jdi.VirtualMachineImpl.waitForTargetReply(VirtualMachineImpl.java:1015)
at com.sun.tools.jdi.PacketStream.waitForReply(PacketStream.java:51)
at com.sun.tools.jdi.JDWP$ObjectReference$InvokeMethod.waitForReply(JDWP.java:4589)
at com.sun.tools.jdi.ObjectReferenceImpl.invokeMethod(ObjectReferenceImpl.java:374)
at processing.mode.java.runner.Runner.findException(Runner.java:701)
at processing.mode.java.runner.Runner.reportException(Runner.java:652)
at processing.mode.java.runner.Runner.exception(Runner.java:595)
at processing.mode.java.runner.EventThread.exceptionEvent(EventThread.java:367)
at processing.mode.java.runner.EventThread.handleEvent(EventThread.java:255)
at processing.mode.java.runner.EventThread.run(EventThread.java:89)
the error message itself varies between P2D and P3D, but they both get a no framebuffer objects available error. I am using processing 2.0b7, please help and let me know if you need more info.
Note: I don't know if this is a separate issue or not, but I am also getting GLSL shader errors to.
Now, here is my code:
Cell[][] Cells = new Cell[50][50];
byte Direction = 1;
byte Times = 1;
int oldwidth = 500;
int oldheight = 500;
void setup() {
size(oldwidth, oldheight, OPENGL);
background(255);
colorMode(HSB,250);
for (int x = 0; x < 50; x++) {
for (int y = 0; y < 50; y++) {
Cells[x][y] = new Cell(x * 5, y * 5, 255, x * (width / 50), y * (height / 50), width / 50, height / 50);
}
}
}
void draw() {
for (int x = 0; x < 50; x++) {
for (int y = 0; y < 50; y++) {
if (width == oldwidth) Cells[x][y].Width = width / 50;
if (height == oldheight) Cells[x][y].Height = height / 50;
if (Direction == 1){
Cells[x][y].Hue += 5;
if (Cells[x][y].Hue > 250) Cells[x][y].Hue -= 250;
}
if (Direction == 2){
Cells[x][y].Saturation -= 5;
if (Cells[x][y].Saturation < 0) Cells[x][y].Saturation += 500;
}
if (Direction == 3){
Cells[x][y].Hue -= 5;
if (Cells[x][y].Hue < 0) Cells[x][y].Hue += 250;
}
if (Direction == 4){
Cells[x][y].Saturation += 5;
if (Cells[x][y].Saturation > 500) Cells[x][y].Saturation -= 500;
}
Cells[x][y].Draw();
}
}
if (Times == 50){
Times = 1;
if (Direction == 4) Direction = 1; else Direction += 1;
} else Times += 1;
delay(10);
}
class Cell {
int X;
int Y;
int Width;
int Height;
float Hue;
float Saturation;
float Brightness;
Cell(color parC, int parX, int parY, int parWidth, int parHeight) {
Hue = hue(parC);
Saturation = saturation(parC);
Brightness = brightness(parC);
X = parX;
Y = parY;
Width = parWidth;
Height = parHeight;
}
Cell(float parHue, float parSaturation, float parBrightness, int parX, int parY, int parWidth, int parHeight) {
Hue = parHue;
Saturation = parSaturation;
Brightness = parBrightness;
X = parX;
Y = parY;
Width = parWidth;
Height = parHeight;
}
void Draw() {
if (Saturation > 250) if (Saturation > 500) stroke(color(Hue,0,Brightness)); else stroke(color(Hue,Saturation - (Saturation - 250) * 2,Brightness)); else stroke(color(Hue,Saturation,Brightness));
if (Saturation > 250) if (Saturation > 500) fill(color(Hue,0,Brightness)); else fill(color(Hue,Saturation - (Saturation - 250) * 2,Brightness)); else fill(color(Hue,Saturation,Brightness));
rect(X, Y, Width, Height);
}
}
I just realized that it is just that my graphics card does not support OPENGL 2.0
Here is a program that has a ball drop and bounce from wherever the mouse is clicked. Would anyone know how to change the rate that the ball drops to the force of gravity?
Im trying to figure out the proper solution to this... but i am having a little trouble. All help and or input would be much appreciated.
float x;
float y;
float yspeed = 0;
float xspeed = 0;
float balldiameter = 10;
float ballradius = balldiameter/2;
void setup() {
size (400,400);
background (255);
fill (0);
ellipseMode(CENTER);
smooth();
noStroke();
x = width/2;
y = height/2;
}
void draw() {
mouseChecks();
boundaryChecks();
ballFunctions();
keyFunctions();
}
void mouseChecks() {
if (mousePressed == true) {
x = mouseX;
y = mouseY;
yspeed = mouseY - pmouseY;
xspeed = mouseX - pmouseX;
}
}
void boundaryChecks() {
if (y >= height - ballradius) {
y = height - ballradius;
yspeed = -yspeed/1.15;
}
if (y <= ballradius) {
y = ballradius;
yspeed = -yspeed/1.35;
}
if (x >= width -ballradius) {
x = width -ballradius;
xspeed = -xspeed/1.10;
}
if (x <= ballradius) {
x = ballradius;
xspeed = -xspeed/1.10;
}
}
void ballFunctions() {
if (balldiameter < 2) {
balldiameter = 2;
}
if (balldiameter > 400) {
balldiameter = 400;
}
ballradius = balldiameter/2;
background(255); //should this be in here?
ellipse (x,y,balldiameter,balldiameter);
yspeed = yspeed += 0.2;
xspeed = xspeed/1.005;
y = y + yspeed;
x = x + xspeed;
}
void keyFunctions() {
if (keyPressed) {
if(keyCode == UP) {
balldiameter +=1;
}
if (keyCode == DOWN) {
balldiameter -=1;
}
}
}
The acceleration of gravity on earth is 9.81 m/s^2. So, if your ball's velocity is 0 at the point the mouse is clicked, the final velocity will be the acceleration integrated in relation to time. This would be (9.81 * t) / 2. Where t is in seconds. The resulting units would be m/sec. You would have to convert meters to some screen space unit for drawing.
I am currently creating a maze using a pair of boolean array (horizontal and vertical) in order to draw lines for the maze.
The maze only every displays 5 bools from the array at one time. Then, I have an user who is always centered and as he moves through the maze the next set of bools are drawn. This is working as it should.
The issue that I am having is: when the user moves to a certain part of the maze the for loop drawing the lines becomes higher than the bool array and therefore crashes the app. Please find below some code snippets.
The onDraw:
protected void onDraw(Canvas canvas) {
canvas.drawRect(0, 0, width, height, background);
int currentX = maze.getCurrentX(),currentY = maze.getCurrentY();
int drawSizeX = 6 + currentX;
int drawSizeY = 6 + currentY;
currentX = currentX - 2;
currentY = currentY - 2;
for(int i = 0; i < drawSizeX - 1; i++) {
for(int j = 0; j < drawSizeY - 1; j++) {
float x = j * totalCellWidth;
float y = i * totalCellHeight;
if(vLines[i + currentY][j + currentX]) {
canvas.drawLine(x + cellWidth, //start X
y, //start Y
x + cellWidth, //stop X
y + cellHeight, //stop Y
line);
}
if(hLines[i + currentY][j + currentX]) {
canvas.drawLine(x, //startX
y + cellHeight, //startY
x + cellWidth, //stopX
y + cellHeight, //stopY
line);
}
}
//draw the user ball
canvas.drawCircle((2 * totalCellWidth)+(cellWidth/2), //x of center
(2 * totalCellHeight)+(cellWidth/2), //y of center
(cellWidth*0.45f), //radius
ball);
}
EDIT 1 - The Move -
public boolean move(int direction) {
boolean moved = false;
if(direction == UP) {
if(currentY != 0 && !horizontalLines[currentY-1][currentX]) {
currentY--;
moved = true;
}
}
if(direction == DOWN) {
if(currentY != sizeY-1 && !horizontalLines[currentY][currentX]) {
currentY++;
moved = true;
}
}
if(direction == RIGHT) {
if(currentX != sizeX-1 && !verticalLines[currentY][currentX]) {
currentX++;
moved = true;
}
}
if(direction == LEFT) {
if(currentX != 0 && !verticalLines[currentY][currentX-1]) {
currentX--;
moved = true;
}
}
if(moved) {
if(currentX == finalX && currentY == finalY) {
gameComplete = true;
}
}
return moved;
}
If there is anything else that I need to clarify please let me know.
Thanks in advance.
drawSizeX/Y indexes over the array when currentX/Y is high enough (length-6)
So limit the values to Math.min(current + 6, array.length)
I am writing a isometric tile based game where the characters can walk freely amongst the tiles, but not be able to cross over to certain tiles that have a collides flag. Sounds easy enough, just check ahead of where the player is going to move using a Screen Coordinates to Tile method and check the tiles array using our returned xy indexes to see if its collidable or not. if its not, then don't move the character. The problem I'm having is my Screen to Tile method isn't spitting out the proper X,Y tile indexes. This method works flawlessly for selecting tiles with the mouse. NOTE: My X tiles go from left to right, and my Y tiles go from up to down. Reversed from some examples on the net. Here's the relevant code:
public Vector2 ScreentoTile(Vector2 screenPoint) {
//Vector2 is just a object with x and y float properties
//camOffsetX,Y are my camera values that I use to shift everything but the
//current camera target when the target moves
//tilescale = 128, screenheight = 480, the -46 offset is to center
// vertically + 16 px for some extra gfx in my tile png
Vector2 tileIndex = new Vector2(-1,-1);
screenPoint.x -= camOffsetX;
screenPoint.y = screenHeight - screenPoint.y - camOffsetY - 46;
tileIndex.x = (screenPoint.x / tileScale) + (screenPoint.y / (tileScale / 2));
tileIndex.y = (screenPoint.x / tileScale) - (screenPoint.y / (tileScale / 2));
return tileIndex;
}
The method that calls this code is:
private void checkTileTouched () {
if (Gdx.input.justTouched()) {
if (last.x >= 0 && last.x < levelWidth && last.y >= 0 && last.y < levelHeight) {
if (lastSelectedTile != null) lastSelectedTile.setColor(1, 1, 1, 1);
Sprite sprite = levelTiles[(int) last.x][(int) last.y].sprite;
sprite.setColor(0, 0.3f, 0, 1);
lastSelectedTile = sprite;
}
}
if (touchDown) {
float moveX=0,moveY=0;
Vector2 pos = new Vector2();
if (player.direction == direction_left) {
moveX = -(player.moveSpeed);
moveY = -(player.moveSpeed / 2);
Gdx.app.log("Movement", String.valueOf("left"));
} else if (player.direction == direction_upleft) {
moveX = -(player.moveSpeed);
moveY = 0;
Gdx.app.log("Movement", String.valueOf("upleft"));
} else if (player.direction == direction_up) {
moveX = -(player.moveSpeed);
moveY = player.moveSpeed / 2;
Gdx.app.log("Movement", String.valueOf("up"));
} else if (player.direction == direction_upright) {
moveX = 0;
moveY = player.moveSpeed;
Gdx.app.log("Movement", String.valueOf("upright"));
} else if (player.direction == direction_right) {
moveX = player.moveSpeed;
moveY = player.moveSpeed / 2;
Gdx.app.log("Movement", String.valueOf("right"));
} else if (player.direction == direction_downright) {
moveX = player.moveSpeed;
moveY = 0;
Gdx.app.log("Movement", String.valueOf("downright"));
} else if (player.direction == direction_down) {
moveX = player.moveSpeed;
moveY = -(player.moveSpeed / 2);
Gdx.app.log("Movement", String.valueOf("down"));
} else if (player.direction == direction_downleft) {
moveX = 0;
moveY = -(player.moveSpeed);
Gdx.app.log("Movement", String.valueOf("downleft"));
}
//Player.moveSpeed is 1
//tileObjects.x is drawn in the center of the screen (400px,240px)
// the sprite width is 64, height is 128
testX = moveX * 10;
testY = moveY * 10;
testX += tileObjects.get(player.zIndex).x + tileObjects.get(player.zIndex).sprite.getWidth() / 2;
testY += tileObjects.get(player.zIndex).y + tileObjects.get(player.zIndex).sprite.getHeight() / 2;
moveX += tileObjects.get(player.zIndex).x + tileObjects.get(player.zIndex).sprite.getWidth() / 2;
moveY += tileObjects.get(player.zIndex).y + tileObjects.get(player.zIndex).sprite.getHeight() / 2;
pos = ScreentoTile(new Vector2(moveX,moveY));
Vector2 pos2 = ScreentoTile(new Vector2(testX,testY));
if (!levelTiles[(int) pos2.x][(int) pos2.y].collides) {
Vector2 newPlayerPos = ScreentoTile(new Vector2(moveX,moveY));
CenterOnCoord(moveX,moveY);
player.tileX = (int)newPlayerPos.x;
player.tileY = (int)newPlayerPos.y;
}
}
}
When the player is moving to the left (downleft-ish from the viewers point of view),
my Pos2 X values decrease as expected but pos2 isnt checking ahead on the x tiles, it is checking
ahead on the Y tiles(as if we were moving DOWN, not left), and vice versa, if the player moves down, it will check ahead on the X values (as if we are moving LEFT, instead of DOWN).
instead of the Y values.
I have an image inside the panel and it moves in a clockwise direction. Now, I want it to move in a random direction and that is my problem.
Could someone give me an idea how to do it?
Here's what I've tried :
private int xVelocity = 1;
private int yVelocity = 1;
private int x, y;
private static final int RIGHT_WALL = 400;
private static final int UP_WALL = 1;
private static final int DOWN_WALL = 400;
private static final int LEFT_WALL = 1;
public void cycle()
{
x += xVelocity;
if (x >= RIGHT_WALL)
{
x = RIGHT_WALL;
if (y >= UP_WALL)
{
y += yVelocity;
}
}
if (y > DOWN_WALL)
{
y = DOWN_WALL;
if (x >= LEFT_WALL)
{
xVelocity *= -1;
}
}
if (x <= LEFT_WALL)
{
x = LEFT_WALL;
if (y <= DOWN_WALL)
{
y -= yVelocity;
}
}
if (y < UP_WALL)
{
y = UP_WALL;
if (x <= RIGHT_WALL)
{
xVelocity *= -1;
}
}
}
Call a method like this to set a random direction:
public void setRandomDirection() {
double direction = Math.random()*2.0*Math.PI;
double speed = 10.0;
xVelocity = (int) (speed*Math.cos(direction));
yVelocity = (int) (speed*Math.sin(direction));
}
Just noticed that you're cycle method will need a little fixing for this to work.
public void cycle() {
x += xVelocity;
y += yVelocity; //added
if (x >= RIGHT_WALL) {
x = RIGHT_WALL;
setRandomDirection();//bounce off in a random direction
}
if (x <= LEFT_WALL) {
x = LEFT_WALL;
setRandomDirection();
}
if (y >= DOWN_WALL) {
y = DOWN_WALL;
setRandomDirection();
}
if (y <= UP_WALL) {
y = UP_WALL;
setRandomDirection();
}
}
(It works, but this is not the most efficient/elegant way to do it)
And if you want some sort of 'random walk' try something like this:
public void cycle() {
//move forward
x += xVelocity;
y += yVelocity;
if (Math.random() < 0.1) {//sometimes..
setRandomDirection(); //..change course to a random direction
}
}
You can increase 0.1 (max 1.0) to make it move more shaky.
Change
y -= yVelocity;
To
if (y>0) {
y = -1*Random.nextInt(3);
} else {
y = Random.nextInt(3);
}