1

I'm trying to recreate Astro-Smash from the Intellivision and I want to make the barrel stay between two angles. I just can't figure out where and how to make the thing stay in between.

I have swapped the function around every which way, trying to simplify the code, I just ended up making it more complicated as seen below.

Main file

let player;
let missiles;
let enemies;

function setup() {
    createCanvas(800, 600);
    angleMode(DEGREES)
    player = new Player();
    enemies = [];
    missiles = [];
}

function keyPressed() {
    if (key == 'a') {
        player.turn(-1);
    } else if (key == 'd') {
        player.turn(1);
    }
}

function scene() {

    // Drawing ground
    ellipseMode(CENTER);
    noStroke();
    fill(112, 78, 33);
    ellipse(width / 2, height, width, 100);

    // Drawing Turret Base
    rectMode(CENTER);
    fill(116, 106, 94);
    rect(width / 2, height, 100, 120);

    // Drawing 'player'
    player.display();


    // Drawing Turret Cover
    translate(width/2, height - 100);
    fill(116, 106, 94);
    ellipse(0, 40, 100, 100);

}

function draw() {
    background(0);
    scene();
}

Player class

class Player {
    constructor() {
        this.position = createVector(0, 0);
        this.l = 10;
        this.h = 100;
        this.heading = 0;
        this.step = 11.25;
        this.minimum = -56.25;
        this.maximum = -56.25;
    }
    turn(d) {
        translate(0, 40);
        if ((this.heading != this.maximum && d == 1) ||
            (this.heading != this.minimum && d == -1)) {
                this.heading += this.step * d;
        } else if ((this.heading == this.minimum && d != 1) ||
            (this.heading == this.maximum && d != -1)){
                this.heading += this.step * d;
        } else {
            return;
        }
    }
    display() {
        push();
        translate(width / 2, height - 100)
        noStroke();
        fill(63);
        rectMode(CENTER);
        rotate(this.heading);
        rect(this.position.x, this.position.y, this.l, this.h);
        pop();
    }

}

I expected to have the missile launcher stay between ±56.25.

R.J. Dunnill
  • 2,049
  • 3
  • 10
  • 21

2 Answers2

1

You're very close, the problem is you're checking equality!

So we have our maximum angle that we want it to turn both clockwise and anti-clockwise denoted by this.maximum.

If we're turning right we check to see whether our current angle this.heading is less (<) our maximum, if so then add to the angle.

If we're turning left we check to see if the angle is greater than our minimum (-this.maximum), if so then take away from the angle.

turn(d) {
    translate(0, 40);
    if (d == 1 && this.heading < this.maximum) {
      this.heading += this.step + d;
    } else if (d == -1 && this.heading > -this.maximum) {
      this.heading += -this.step + d;
    }
}

let player;
let missiles;
let enemies;

function setup() {
    createCanvas(800, 600);
    angleMode(DEGREES)
    player = new Player();
    enemies = [];
    missiles = [];
}

function keyPressed() {
    if (key == 'a') {
        player.turn(-1);
    } else if (key == 'd') {
        player.turn(1);
    }
}

function scene() {

    // Drawing ground
    ellipseMode(CENTER);
    noStroke();
    fill(112, 78, 33);
    ellipse(width / 2, height, width, 100);

    // Drawing Turret Base
    rectMode(CENTER);
    fill(116, 106, 94);
    rect(width / 2, height, 100, 120);

    // Drawing 'player'
    player.display();


    // Drawing Turret Cover
    translate(width/2, height - 100);
    fill(116, 106, 94);
    ellipse(0, 40, 100, 100);

}

function draw() {
    background(0);
    scene();
}

class Player {
    constructor() {
        this.position = createVector(0, 0);
        this.l = 10;
        this.h = 100;
        this.heading = 0;
        this.step = 11.25;
        
        this.maximum = 56.25;
    }
    turn(d) {
        translate(0, 40);
        if (d == 1 && this.heading < this.maximum) {
          this.heading += this.step + d;
        } else if (d == -1 && this.heading > -this.maximum) {
          this.heading += -this.step + d;
        }
    }
    display() {
        push();
        translate(width / 2, height - 100)
        noStroke();
        fill(63);
        rectMode(CENTER);
        rotate(this.heading);
        rect(this.position.x, this.position.y, this.l, this.h);
        pop();
    }

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
Luke Garrigan
  • 4,571
  • 1
  • 21
  • 29
0

Thats because of floating point math. It is very unlikely that this.heading will exactly match this.minimum (because values are slightly rounded during the calculations). Instead of == use <= and >=.

I'd write turn as:

  turn(direction) {
     this.heading = Math.min(this.maximum, Math.max(this.minimum, this.heading + this.step * direction));
  }
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151