I've got a float variable called angleOfGun which is containing the angle of the gun on the screen, which is constantly moving. I want to save the angle that the gun was at when the user clicks the screen in a separate float variable, currentAngle. The problem is, currentAngle keeps updating with angleOfGun because angleOfGun is changing..
Do you have any ideas of how I could save an instance of angleOfGun into currentAngle without currentAngle updating any more after the initial value is set? Thanks!
float angleOfGun = 1;
//boolean for direction of rotation
boolean clockwise = false;
/**
* Action to perform on clock tick
*
* #param g the canvas object on which to draw
*/
public void tick(Canvas g) {
int height = g.getHeight();
int width = g.getWidth();
//rotate/draw the gun
g.save();
g.rotate(angleOfGun, width - 5, 5);
g.drawRect(new RectF(width - 40, 0, width, 60), bluePaint);
g.restore();
if(ballPosition != null)
{
float currentAngle = angleOfGun;
g.save();
g.rotate(currentAngle, width - 5, 5);
ballPosition.x = ballPosition.x - ballVelocity.x;
ballPosition.y = ballPosition.y - ballVelocity.y;
g.drawCircle(ballPosition.x, ballPosition.y, 10, greenPaint);
g.restore();
}
if(clockwise)
{
angleOfGun = (angleOfGun - 1) % 360;
if(angleOfGun == 0)
{
clockwise = false;
}
}
else
{
angleOfGun = (angleOfGun + 1) % 360;
if(angleOfGun == 90)
{
clockwise = true;
}
}
}
/**
* callback method, run when when surface is touched
*/
public void onTouch(MotionEvent event) {
if(ballPosition == null && shoot == false)
{
shoot = true;
ballPosition = new PointF(0,0);
ballVelocity = new PointF(0,0);
ballPosition.x = 1280;
ballPosition.y = 0;
ballVelocity.x = 0;
ballVelocity.y = -5;
}
}
In your class you have method tick() there is line in the code:
float currentAngle = angleOfGun;
So you constantly assign value of angleOfGun to currentAngle. So after this declaration in your code you simply can use currentAnglein place of angleOfGun in your code(and vice versa) and this will have no effect on anything, as they both store same value.
Don't forget that Java is OOP language, so you can take advantage of that. My approach would be to create class called Anglewhere i can have private static float currentAngle field and private float gunAngle. By creating mutators, value of this variables could be manipulated to satisfy any need. This approach will help by simplifying code and would give you flexibility to make further changes by adding or removing methods.
I would create another variable gunLocked (boolean). When you set the gun angle just lock it, and test to see if it is locked. If it is don't update, otherwise do.
if(ballPosition != null)
{
if (!gunLocked)
{
float currentAngle = angleOfGun;
gunLocked = true;
g.save();
g.rotate(currentAngle, width - 5, 5);
ballPosition.x = ballPosition.x - ballVelocity.x;
ballPosition.y = ballPosition.y - ballVelocity.y;
g.drawCircle(ballPosition.x, ballPosition.y, 10, greenPaint);
g.restore();
}
}
Of course this does mean that you'll have to create another way to unlock the gun (on a button press maybe? such as when the user moved the gun)
As you are using primitive types ideally it should not happen. Try this:
declare currentAngle also globally like angleOfGun
Related
I am making a little ant colony simulation in Processing (4).
I have an Ant class, with a sense() , a move()and a render() function.
I also have a Food class with only a position PVector.
My sense class loops through all Foods in a given radius, and it is meant to only 'see' the ones inside a given view angle.
In my render() function I have an arc to visualise this (I do some division and addition so the arc centres in front of the rectangle):
void render() {
// Draw a rectangl rotated in the direction of velocity
float theta = velocity.heading() + radians(90);
if(detectFood) // a Boolean set in sense()
fill(0,173,67); // turns green
else {
stroke(255);
pushMatrix();
translate(position.x, position.y);
fill(200, 100);
rotate(theta); // I copied the rotation code from somewhere :)
rect(0-r/2,0-r,r,r*2); // r is a float used to control size
arc(0, 0, viewRadius * 2, viewRadius * 2, radians(270 - viewAngle/2), radians(270 + viewAngle/2)); // viewRadius is a float set in the constructor
popMatrix();
}
}
This ends up looking like this:
My sense() code uses trigonometry to calculate the angle and the distance (I am using my own calculations because wasn't sure the inbuilt ones did what I thought they did):
void sense() {
if (!detectFood) {
float closest = viewRadius;
Food selected = null;
for (Food fd : foods){
float foodDist = position.dist(fd.position);
if(foodDist <= viewRadius) {
float xs = position.x-fd.position.x;
float ys = position.y-fd.position.y;
float Angle = atan2(abs(ys), abs(xs));
float begin = radians(270 - viewAngle/2);
float end = radians(270 + viewAngle/2);
if(begin < Angle && Angle < end && foodDist < closest){
selected = fd;
closest = foodDist;
println("found food");
}
}
}
if (selected != null){
detectFood = true;
foodFocused = selected;
}
} else {
if(position.dist(foodFocused.position) < r) {
takeFood();
detectFood = false;
}
}
}
The problem is that because I rotate the shape (and the arc with it), my sensing code basically never works. Is there a way to account for rotation in trigonometry or maybe an easier way of doing this? Any help would be apreciated
I am looking for some help with some game code i have inherited from a flight sim. The code below simulates bombs exploding on the ground, it works fine but i am trying to refine it.
At the moment it takes a random value for x and y as a start point and then adds another random value between -20 and 20 to this. It works ok, but doesn't simulate bombs dropping very well as the pattern does not lay along a straight line/
What i would like to achieve though is all x and y points after the first random values, to lay along a straight line, so that the effects called for all appear to lay in a line. It doesn't matter which way the line is orientated.
Thanks for any help
slipper
public static class BombUnit extends CandCGeneric
{
public boolean danger()
{
Point3d point3d = new Point3d();
pos.getAbs(point3d);
Vector3d vector3d = new Vector3d();
Random random = new Random();
Aircraft aircraft = War.GetNearestEnemyAircraft(this, 10000F, 9);
if(counter > 10)
{
counter = 0;
startpoint.set(point3d.x + (double)(random.nextInt(1000) - 500), point3d.y + (double)(random.nextInt(1000) - 500), point3d.z);
}
if(aircraft != null && (aircraft instanceof TypeBomber) && aircraft.getArmy() != myArmy)
{
World.MaxVisualDistance = 50000F;
counter++;
String s = "weapon.bomb_std";
startpoint.x += random.nextInt(40) - 20;
startpoint.y += random.nextInt(40) - 20;
Explosions.generate(this, startpoint, 7F, 0, 30F, !Mission.isNet());
startpoint.z = World.land().HQ(startpoint.x, startpoint.y);
MsgExplosion.send(this, s, startpoint, getOwner(), 0.0F, 7F, 0, 30F);
Engine.land();
int i = Landscape.getPixelMapT(Engine.land().WORLD2PIXX(startpoint.x), Engine.land().WORLD2PIXY(startpoint.y));
if(firecounter < 100 && i >= 16 && i < 20)
{
Eff3DActor.New(null, null, new Loc(startpoint.x, startpoint.y, startpoint.z + 5D, 0.0F, 90F, 0.0F), 1.0F, "Effects/Smokes/CityFire3.eff", 300F);
firecounter++;
}
super.setTimer(15);
}
return true;
}
private static Point3d startpoint = new Point3d();
private int counter;
private int firecounter;
public BombUnit()
{
counter = 11;
firecounter = 0;
Timer1 = Timer2 = 0.05F;
}
}
The code in the question is a mess, but ignoring this and trying to focus on the relevant parts: You can generate a random position for the first point, and a random direction, and then walk along this direction in several steps.
(This still raises the question of whether the direction is really not important. Wouldn't it matter if only the first bomb was dropped in the "valid" area, and the remaining ones outside of the screen?)
However, the relevant code could roughly look like this:
class Bombs
{
private final Random random = new Random(0);
int getScreenSizeX() { ... }
int getScreenSizeY() { ... }
// Method to drop a single bomb at the given position
void dropBombAt(double x, double y) { ... }
void dropBombs(int numberOfBombs, double distanceBetweenBombs)
{
// Create a random position in the screen
double currentX = random.nextDouble() * getScreenSizeX();
double currentY = random.nextDouble() * getScreenSizeY();
// Create a random step size
double directionX = random.nextDouble();
double directionY = random.nextDouble();
double invLength = 1.0 / Math.hypot(directionX, directionY);
double stepX = directionX * invLength * distanceBetweenBombs;
double stepY = directionY * invLength * distanceBetweenBombs;
// Drop the bombs
for (int i=0; i<numberOfBombs; i++)
{
dropBombAt(currentX, currentY);
currentX += stepX;
currentY += stepY;
}
}
}
I am assuming your startpoint is a StartPoint class with x,y,z coordinates as integers in it.
I hope I have understood your problem correctly. It looks like you either want to create a vertical explosion or a horizontal explosion. Since an explosion always occurs on ground, the z coordinate will be zero. Now you can vary one of x or y coordinate to give you a random explosion along a straight line. Whether you choose x or y could be fixed or could be randomized itself. A potential randomized solution below:
public boolean danger() {
// stuff
int orientation = Random.nextInt(2);
if(aircraft != null && (aircraft instanceof TypeBomber) && aircraft.getArmy() != myArmy)
{
// stuff
startPoint = randomizeStartPoint(orientation, startPoint);
// stuff
}
}
StartPoint randomizeStartPoint(int orientation, StartPoint startPoint) {
if(orientation == 0) {
startPoint.x += random.nextInt(40) - 20;
}
else {
startPoint.y += random.nextInt(40) - 20;
}
return startPoint;
}
In response to the image you uploaded, it seems that the orientation of the explosion need not necessarily be horizontal or vertical. So the code I posted above gives a limited solution to your problem.
Since you want any random straight line, your problem boils down to two sub parts:
1. Generate a random straight line equation.
2. Generate random point along this line.
Now, a straight line equation in coordinate geometry is y = mx + c where m is the slope and c is the constant where the line crosses the y-axis. The problem with c is that it gives rise to irrational coordinates. I am assuming you are looking for integer coordinates only, since this will ensure that your points are accurately plotted. (You could do with rational fractions, but then a fraction like 1/3 will still result in loss of accuracy). The best way to get rid of this irrational problem is to get rid of c. So now your straight line always looks like y = mx. So for step one, you have to generate a random m.
Then for step 2, you can either generate a random x or random y. It doesn't matter which one, since either one will result in random coordinates.
Here is a possible code for the solution:
int generateRandomSlope() {
return Random.nextInt(100); // arbitrarily chose 100.
}
int randomizeStartPoint(int m, StartPoint startPoint) { // takes the slope we generated earlier. without the slope, your points will never be on a straight line!
startPoint.x += random.nextInt(40) - 20;
startPoint.y += x * m; // because a line equation is y = mx
return startPoint;
}
public boolean danger() {
// stuff
int m = generateRandomSlope(); // you may want to generate this elsewhere so that it doesn't change each time danger() is called.
if(aircraft != null && (aircraft instanceof TypeBomber) && aircraft.getArmy() != myArmy)
{
// stuff
startPoint = randomizeStartPoint(m, startPoint);
// stuff
}
}
Again, this is not a complete or the best solution.
I want to implement a kind of drums. For every hit I want to play a song. So I need to detect every "hit" and the position. before I start implementing a function who will analyse the positions and detect "hits" I want to be sure that there is no other solution, so is there any event, gesture detection who allow me to detect that ?
As far as I know there is no "event" that is defined natively other than stream callbacks which are called when you receive data such as the joint positions and depth image which should be enough to get you started.
I would take a look at this:https://code.google.com/p/kineticspace/ in order to know what to expect or how to proceed with your own code.
Once you manage to get the skeleton data just find where the hand is at that time, put a threshold to its position and start tracking for a certain amount time and see if its movement path fits your pattern for a particular gesture such as "translation in y direction for x amount of seconds". Then you have very simple "hit" gesture detection. This can get as complex as you need, but there is not much to it at the basics in terms of what you receive from the library side.
Good luck.
I made a drum kit with the Kinect using this is a wonderful class for placing and using boxes in Kinect.
Import Libraries:
import processing.opengl.*;
import SimpleOpenNI.*;
Use something like this bit of code inside your Setup()
myTrigger = new Hotpoint(200, 10, 800, size);
Use the methods inside your draw()
if(myTrigger.currentlyHit()) {
myTrigger.play();
println("trigger hit");
}
Use the following methods inside this class!
class Hotpoint {
PVector center;
color fillColor;
color strokeColor;
int size;
int pointsIncluded;
int maxPoints;
boolean wasJustHit;
int threshold;
Hotpoint(float centerX, float centerY, float centerZ, int boxSize) {
center = new PVector(centerX, centerY, centerZ);
size = boxSize;
pointsIncluded = 0;
maxPoints = 1000;
threshold = 0;
fillColor = strokeColor = color(random(255), random(255), random(255));
}
void setThreshold( int newThreshold ){
threshold = newThreshold;
}
void setMaxPoints(int newMaxPoints) {
maxPoints = newMaxPoints;
}
void setColor(float red, float blue, float green){
fillColor = strokeColor = color(red, blue, green);
}
boolean check(PVector point) {
boolean result = false;
if (point.x > center.x - size/2 && point.x < center.x + size/2) {
if (point.y > center.y - size/2 && point.y < center.y + size/2) {
if (point.z > center.z - size/2 && point.z < center.z + size/2) {
result = true;
pointsIncluded++;
}
}
}
return result;
}
void draw() {
pushMatrix();
translate(center.x, center.y, center.z);
fill(red(fillColor), blue(fillColor), green(fillColor),
255 * percentIncluded());
stroke(red(strokeColor), blue(strokeColor), green(strokeColor), 255);
box(size);
popMatrix();
}
float percentIncluded() {
return map(pointsIncluded, 0, maxPoints, 0, 1);
}
boolean currentlyHit() {
return (pointsIncluded > threshold);
}
boolean isHit() {
return currentlyHit() && !wasJustHit;
}
void clear() {
wasJustHit = currentlyHit();
pointsIncluded = 0;
}
}
Please look at the following structure of my pong game.
gameLoop(); method
//Only run this in another Thread!
private void gameLoop()
{
//This value would probably be stored elsewhere.
final double GAME_HERTZ = 30.0;
//Calculate how many ns each frame should take for our target game hertz.
final double TIME_BETWEEN_UPDATES = 1000000000 / GAME_HERTZ;
//At the very most we will update the game this many times before a new render.
//If you're worried about visual hitches more than perfect timing, set this to 1.
final int MAX_UPDATES_BEFORE_RENDER = 5;
//We will need the last update time.
double lastUpdateTime = System.nanoTime();
//Store the last time we rendered.
double lastRenderTime = System.nanoTime();
//If we are able to get as high as this FPS, don't render again.
final double TARGET_FPS = 60;
final double TARGET_TIME_BETWEEN_RENDERS = 1000000000 / TARGET_FPS;
//Simple way of finding FPS.
int lastSecondTime = (int) (lastUpdateTime / 1000000000);
while (running)
{
double now = System.nanoTime();
int updateCount = 0;
if (!paused)
{
//Do as many game updates as we need to, potentially playing catchup.
while( now - lastUpdateTime > TIME_BETWEEN_UPDATES && updateCount < MAX_UPDATES_BEFORE_RENDER )
{
updateGame();
lastUpdateTime += TIME_BETWEEN_UPDATES;
updateCount++;
}
//If for some reason an update takes forever, we don't want to do an insane number of catchups.
//If you were doing some sort of game that needed to keep EXACT time, you would get rid of this.
if ( now - lastUpdateTime > TIME_BETWEEN_UPDATES)
{
lastUpdateTime = now - TIME_BETWEEN_UPDATES;
}
//Render. To do so, we need to calculate interpolation for a smooth render.
float interpolation = Math.min(1.0f, (float) ((now - lastUpdateTime) / TIME_BETWEEN_UPDATES) );
//float interpolation = 1.0f;
drawGame(interpolation);
lastRenderTime = now;
//Yield until it has been at least the target time between renders. This saves the CPU from hogging.
while ( now - lastRenderTime < TARGET_TIME_BETWEEN_RENDERS && now - lastUpdateTime < TIME_BETWEEN_UPDATES)
{
Thread.yield();
//This stops the app from consuming all your CPU. It makes this slightly less accurate, but is worth it.
//You can remove this line and it will still work (better), your CPU just climbs on certain OSes.
//FYI on some OS's this can cause pretty bad stuttering. Scroll down and have a look at different peoples' solutions to this.
try {Thread.sleep(1);} catch(Exception e) {}
now = System.nanoTime();
}
}
}
}
updateGame(); method
if(p1_up){
if(player.equals("p1")){
p1.moveUp();
}
else
{
p2.moveUp();
}
}
else if(p1_down){
if(player.equals("p1")){
p1.moveDown();
}
else
{
p2.moveDown();
}
}
moveUp(); moveDown(); method of paddle
public void moveUp(){
last_y = y;
last_x = x;
y -= 50.0;
}
public void moveDown(){
last_y = y;
last_x = x;
y += 50.0;
}
drawGame(interpolation); method
public void paintComponent(Graphics g)
{
super.paintComponent(g);
for(int i=0;i<balls.size();i++){
paintBall(g, balls.get(i));
}
drawPaddle(g, p1);
drawPaddle(g, p2);
}
public void drawPaddle(Graphics g, Paddle p){
paddle_drawX = (int)((p.x - p.last_x)*interpolation + p.last_x);
paddle_drawY = (int)((p.y - p.last_y)*interpolation + p.last_y);
g.drawRect(paddle_drawX, paddle_drawY, 10, 50);
}
I am a beginner in game programming so i don't have a good idea about game loops. I found the above fixed time-step game loop in the internet and used it as the game loop for my game. The loop makes the ball move smoothly but the paddle isn't staying at one place when moved. When I move my paddle by pressing one down key stroke then the paddle keeps shaking
without stopping in one spot. The y coordinates of the paddle keeps changing like
33, 45, 20, 59, 34, 59, 34, 59, 33, 59, 34, 58
I know the problem is in interpolation value as it keeps changing value that will change the y coordinate of paddle in render. I have been thinking about this for a while and i don't know how to make the game loop work for any movements so i have come here for some help. I appreciate any suggestion/help!
Here is my full Paddle class.
public class Paddle
{
float x;
float y;
float last_y;
float last_x;
public Paddle(int x, int y)
{
this.x = x;
this.y = y;
this.last_x = x;
this.last_y = y;
}
public void setNewX(int d){
last_y = y;
last_x = x;
x = d;
}
public void setNewY(int d){
last_y = y;
last_x = x;
y = d;
}
public void moveUp(){
last_y = y;
last_x = x;
y -= 50.0;
}
public void moveDown(){
last_y = y;
last_x = x;
y += 50.0;
}
}
and i initiate the paddle position in the main class through global variable.
public Paddle p1 = new Paddle(10, 10);
public Paddle p2 = new Paddle(950, 10);
I have following event listeners for handling key strokes.
Action handle_up_action = new AbstractAction(){
public void actionPerformed(ActionEvent e){
p1_up = true;
}
};
Action handle_up_action_released = new AbstractAction(){
public void actionPerformed(ActionEvent e){
p1_up = false;
}
};
Action handle_down_action = new AbstractAction(){
public void actionPerformed(ActionEvent e){
p1_down = true;
}
};
Action handle_down_action_released = new AbstractAction(){
public void actionPerformed(ActionEvent e){
p1_down = false;
}
};
What are you trying to achieve with interpolation? From my understanding, it represents the percentage of time elapsed between previous previous and next "update time".
So it should progress continuously from 0 to 1 each 33.3 ms.
I don't know how you use this interpolation variable in the paintBall method, but for the paddles, it will draw your paddle at a "pseudo random position" between p.x;p.y and p.last_x;p.last_y (depending on the time between the two updateGame()).
In order to correct this, from your loop logic, you should understand that every game entity (balls, paddles, ...) must have two states (the positions):
- the logical state, which is updated only each TIME_BETWEEN_UPDATES
- the visual state, which can be updated anytime, at each render.
It is the same as if you have a set of points (which represent the logical states) and you want to interpolate anywhere between this points (reprensenting the visual state).
Your code is like this.
First solution
The simplest way to correct the paddle shaking, is to avoid the interpolation and use:
public void drawPaddle(Graphics g, Paddle p){
paddle_drawX = (int)p.x;
paddle_drawY = (int)p.y;
g.drawRect(paddle_drawX, paddle_drawY, 10, 50);
}
But your movement will look like this (visual position will be changed only each TIME_BETWEEN_UPDATES)
Second solution
You want p.x;p.y to be the logical position, but the visual position should be interpolated between p.last_x;p.last_y and the logical position if the rendering is done between the input processing and the next updateGame(): you must reset p.last_x;p.last_y when updateGame() is called. To achieve this, call the paddles' updateMovement() method inside updateGame().
public void updateMovement(){
last_y = y;
last_x = x;
}
You can have other solutions, such as to use a speed variable or a movement function, in order to have a smooth movement, accelerations, and so on. It is mainly a generalisation of second solution. It requires bigger changes, but it is more flexible and powerful. To achieve this, you may want to store in paddles the last "update position", and all movement-related variables, such as movement start date. Add a method to retrieve the "visual position" that can be called with any date between two updates, and a method to update the "logical position" called each updateGame().
(The event listener is in another class) When Game.render = true, i get a constant stream of bullets that look more like a laser-beam, i want there to be gaps. What I mean is that I would like the bullets to be generated as if they were being fired from a machine gun. I know i should add a time or something, but I'm not sure how to do that, to get the effect I want. Any help would be greatly appreciated because I've been trying to get this to work for about an hour now.
import java.util.ArrayList;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
public class Bullet {
// ArrayList
#SuppressWarnings("unchecked")
static ArrayList<Bullet> arrL = new ArrayList();
public Bullet(int x , int y) throws SlickException{
}
public static void update(GameContainer gc, int u) throws SlickException{
// when the left mouse button is clicked Game.fire = true, the key listener is in another class
if(Game.fire){
Bullet b = new Bullet(5,5);
arrL.add(b);
reloaded = false;
} if(!reloaded){
}
}
public static void renderBullets(GameContainer gc, Graphics g, int x, int y) {
// draws a new bullet for every 'bullet object' in the ArrayList called arrL
for(Bullet b : arrL){
g.drawRect(x,y,10,10);
x++;
}
}
}
What I do most frequently in this kind of situation is add a time variable that I subtract the delta (the variable you have as u) from every update until it goes below 0, at which point I reset it:
// Set this to whatever feels right for the effect you're trying to achieve.
// A larger number will mean a longer delay.
private static int default_bullet_delay = 500;
private static int time = 0;
public static void update (GameContainer gc, int u) throws SlickException {
time -= u;
if (time <= 0 && Game.fire) {
fireBullet(); // Replace this with your code for firing the bullet
time = default_bullet_delay; // Reset the timer
}
// The rest of the update loop...
}
Basically, even if Game.fire is true the bullet won't fire until the timer counts down. Once that happens, the timer is set and the next bullet can't fire until the timer counts down again. If you set this to something reasonably small then there should be a bit of a gap between each bullet.
This is how I did this:
boolean reloaded = false; // Start with a reload becouse weapon not reload itself
float reloadTime = 100; // This is the "timer" (the value doesnt matter)
float startReloadTime = 100; // This is the actual reload time
private void shoot(int delta, float screenWidth, float screenHeight) {
// reload if not reloaded
if (!reloaded) {
reloadTime -= 0.5f * delta; // As I said, this is the timer
// If the reload finished, set the timer back to the reload time
if (reloadTime <= 0) {
reloaded = true; // reloaded, we can shoot
reloadTime = startReloadTime;
}
}
// Shoot only if reloaded
if (reloaded) {
// This is some direction calculating, ignore for now
float mouseWorldX = (x + (mouseX - screenWidth / 2));
float mouseWorldY = (y + (mouseY - screenHeight / 2));
float randomX = (float) Math.random() * (2000 / mouseWorldX);
float randomY = (float) Math.random() * (2000 / mouseWorldY);
mouseWorldX += randomX;
mouseWorldY += randomY;
// Add a new bullet element to the world (where will be rendered)
world.add(new Shot(world, camera, x + width / 2, y + height / 2, mouseWorldX - 2.5f, mouseWorldY - 2.5f, 5, 5, new Color(1, 0, 0, 1f)));
// We need to reload
reloaded = false;
}
}