Live Stream #70: Coding Challenges: Asteroids and Pixel Sorting

[ad_1]
In this Live Stream, I take on two Coding Challenges. First, I make a version of the classic Atari game Asteroids using JavaScript and HTML5 canvas with the p5.js library. I then implement “Pixel Sorting” in Processing (Java). I sort the pixels of an image by brightness and hue.

8:45 – Short Q&A
22:58 – Coding Challenge: Asteroids with p5.js
1:56:17 – Coding Challenge: Pixel Sorting in Processing
2:25:00 – Conclusion/Q&A

Support this channel on Patreon:

Send me your questions and coding challenges!:

Contact:

Links discussed in this video:
Asteroids on Wikipedia:
Mike Bostock’s page on Visualizing Algorithms:
My Trigonometry and Polar Coordinates video:
Sirajology’s channel:
Kittens Song:
This Dot Song on Soundcloud:

Source Code for the all Video Lessons:

Asteroids Code:
Asteroids Game:

p5.js:
Processing:

For More Live Streams:
For More Coding Challenges:

Help us caption & translate this video!


Posted

in

by

Tags:

Comments

21 responses to “Live Stream #70: Coding Challenges: Asteroids and Pixel Sorting”

  1. scpDgJ Avatar

    I made a processing version of asteroids, feel free to laugh at me for each error you find in the code πŸ™‚

    import java.util.Iterator; // Used to remove objects while looping
    import java.util.LinkedList;

    final color faded_white = color(255, 185);
    final color black = color(0);
    final color light_blue1 = color(187, 255, 255);
    final color light_blue2 = color(160, 255, 255);
    final color light_blue3 = color(213, 255, 255);
    final color green = color(0, 255, 0);
    final int initialObstacles = 4;
    Ship ship; // The ship we control
    LinkedList<Asteroid> asteroids;
    LinkedList<Enemy> enemies;
    ArrayList<Asteroid> splitedAsteroids; // Used in the process of splitting asteroids
    Asteroid[] temp; // Used in the process of splitting asteroids
    final String fileName = "savefile.txt";
    int recordScore = 0;
    int score = 0, maxScore = 0;
    int level = 0;
    boolean gamePaused = false;

    void setup() {
    /**size(1600, 800);/*/fullScreen();//*/
    splitedAsteroids = new ArrayList();
    ship = new Ship();
    asteroids = new LinkedList();
    enemies = new LinkedList();
    increaseObstacles(initialObstacles * ++level);
    String[] test = loadStrings(fileName);
    if (test == null) { // If file doesn't exist
    PrintWriter output = createWriter(fileName);
    output.print("0");
    output.flush();
    output.close();
    } else
    recordScore = int(test[0]);
    }

    void increaseObstacles(int howMany) {
    int randInt = int(random(100));
    if (randInt < 1)
    increaseEnemies(5 * initialObstacles);
    else {
    if (randInt < 10) {
    increaseEnemies(2);
    howMany -= 4;
    }
    else if (randInt < 33) {
    increaseEnemies(1);
    howMany -= 2;
    }
    increaseAsteroids(howMany);
    }
    }

    void increaseAsteroids(int howMany) {
    for (int i = 0; i < howMany; i++)
    asteroids.add(new Asteroid(random(width), random(height), random(-Asteroid.maxVelMag, Asteroid.maxVelMag),
    random(-Asteroid.maxVelMag, Asteroid.maxVelMag), random(-Asteroid.maxAngularVel, Asteroid.maxAngularVel)));
    }

    void increaseEnemies(int howMany) {
    for (int i = 0; i < howMany; i++)
    enemies.add(new Enemy(ship));
    }

    void keyPressed() {
    if (key == CODED) {
    ship.intangible = false;
    switch(keyCode) {
    case UP: ship.accelerate(); break;
    case RIGHT: ship.angularVel = ship.angVelMag; break;
    case LEFT: ship.angularVel = -ship.angVelMag;
    }
    }
    else switch(key) {
    case ' ': ship.shoot();
    ship.intangible = false;
    break;
    case 'w': increaseObstacles(initialObstacles); break;
    case 'p': if (gamePaused)
    loop();
    gamePaused = !gamePaused;
    break;
    case 'e': enemies.add(new Enemy(ship)); break;
    case 'k': if (!enemies.isEmpty())
    enemies.remove();
    else if (!asteroids.isEmpty())
    asteroids.remove();
    break;
    case 'q': if (maxScore > recordScore)
    saveStrings(fileName, new String[] {str(maxScore)});
    exit();
    }
    }

    void keyReleased() {
    ship.angularVel = 0;
    }

    void wrapAroundScreen(AbstractMover mover, float offset) {
    if (mover.pos.x > width + offset)
    mover.pos.x = -offset;
    else if (mover.pos.x < -offset)
    mover.pos.x = width + offset;
    if (mover.pos.y > height + offset)
    mover.pos.y = -offset;
    else if (mover.pos.y < -offset)
    mover.pos.y = height + offset;
    }

    boolean areIntercepting(Hitbox object1, Hitbox object2) {
    PVector pos1 = object1.getPos();
    PVector pos2 = object2.getPos();
    int hitbox_r1 = object1.getHitbox_r();
    int hitbox_r2 = object2.getHitbox_r();
    return dist(pos1.x, pos1.y, pos2.x, pos2.y) < hitbox_r1 + hitbox_r2;
    }

    boolean areIntercepting(Hitbox object, Bullet bullet) {
    PVector pos = object.getPos();
    int hitbox_r = object.getHitbox_r();
    return dist(pos.x, pos.y, bullet.pos.x, bullet.pos.y) < hitbox_r;
    }

    void printScores() {
    pushMatrix();
    textSize(48);
    fill(light_blue2);
    textAlign(LEFT, TOP);
    text(str(score), 50, 50);
    textAlign(RIGHT, TOP);
    text(str(maxScore), width – 50, 50);
    textAlign(RIGHT, BOTTOM);
    text(str(recordScore), width – 50, height – 50);
    popMatrix();
    }

    void reset() {
    ship.reset();
    score = level = 0;
    asteroids.clear();
    enemies.clear();
    }

    void draw() {
    background(black);
    printScores();

    // Draw asteroids
    for (Asteroid asteroid : asteroids)
    asteroid.display();

    // Draw enemies and their bullets
    for (Enemy enemy : enemies) {
    enemy.display();
    for (Bullet bullet : enemy.firedBullets)
    bullet.display();
    }

    // Draw ship and its bullets
    ship.display();
    for (Bullet bullet : ship.firedBullets)
    bullet.display();

    // Update ship and its bullets
    ship.update();
    for (Bullet bullet : ship.firedBullets)
    bullet.update();

    // Update enemies and their bullets
    for (Enemy enemy : enemies) {
    enemy.update();
    for (Bullet bullet : enemy.firedBullets)
    bullet.update();
    }

    // Update asteroids
    for (Asteroid asteroid : asteroids)
    asteroid.update();

    // Remove ship's dead bullets
    for (Iterator<Bullet> i = ship.firedBullets.iterator(); i.hasNext(); ) {
    Bullet bullet = i.next();
    if (bullet.dead)
    i.remove();
    }

    // Remove enemies' dead bullets
    for (Enemy enemy : enemies)
    for (Iterator<Bullet> i = enemy.firedBullets.iterator(); i.hasNext(); ) {
    Bullet bullet = i.next();
    if (bullet.dead)
    i.remove();
    }

    if (!ship.intangible) {
    // Collide ship with asteroids
    for (Asteroid asteroid : asteroids)
    if (areIntercepting(asteroid, ship)) {
    reset();
    break;
    }

    // Collide ship with enemies and their bullets
    outerLoop:
    for (Enemy enemy : enemies) {
    if (areIntercepting(enemy, ship)) {
    reset();
    break;
    }
    for (Bullet bullet : enemy.firedBullets)
    if (areIntercepting(ship, bullet)) {
    reset();
    break outerLoop;
    }
    }
    }

    // Collide our bullets with asteroids
    for (Iterator<Asteroid> i = asteroids.iterator(); i.hasNext(); ) {
    Asteroid asteroid = i.next();
    for (Bullet bullet : ship.firedBullets)
    if (areIntercepting(asteroid, bullet)) {
    if (!splitedAsteroids.isEmpty())
    splitedAsteroids.clear();
    if (asteroid.hitbox_r/2 >= Asteroid.minHitbox_r) {
    temp = asteroid.split();
    splitedAsteroids.add(temp[0]);
    splitedAsteroids.add(temp[1]);
    }
    i.remove();
    bullet.dead = true;
    if (++score < 0)
    score = MAX_INT;
    break;
    }
    }
    while (!splitedAsteroids.isEmpty())
    asteroids.add(splitedAsteroids.remove(splitedAsteroids.size()-1));

    // Collide our bullets with enemies
    for (Iterator<Enemy> i = enemies.iterator(); i.hasNext(); ) {
    Enemy enemy = i.next();
    for (Bullet bullet : ship.firedBullets)
    if (areIntercepting(enemy, bullet)) {
    i.remove();
    bullet.dead = true;
    score += 2;
    if (score < 0)
    score = MAX_INT;
    break;
    }
    }

    if (score > maxScore)
    maxScore = score;
    if (asteroids.isEmpty() && enemies.isEmpty()) { // Level Completed!
    if (++level < 0)
    level = MAX_INT;
    increaseObstacles(constrain(level * initialObstacles, 1, 10 * initialObstacles));
    ship.reset();
    }
    if (gamePaused) {
    pushMatrix();
    fill(light_blue2);
    textSize(48);
    textAlign(CENTER, CENTER);
    text("Paused", width/2, height/2 – 75);
    popMatrix();
    noLoop();
    }
    }

    interface AI {
    void artificialIntelligence();
    }

    interface Hitbox {
    int getHitbox_r();
    PVector getPos();
    }

    abstract class AbstractMover {
    boolean intangible = false;
    final PVector pos;
    final PVector vel;
    float angle;
    float angularVel;

    AbstractMover(float x, float y) {
    this(x, y, 0, 0, -HALF_PI, 0);
    }

    AbstractMover(float x, float y, float vx, float vy, float angle, float angularVel) {
    pos = new PVector();
    vel = new PVector();
    set(x, y, vx, vy, angle, angularVel);
    }

    void set(float x, float y) {
    set(x, y, 0, 0, -HALF_PI, 0);
    }

    void set(float x, float y, float vx, float vy, float angle, float angularVel) {
    pos.set(x, y);
    vel.set(vx, vy);
    this.angle = angle;
    this.angularVel = angularVel;
    }

    void update() {
    move();
    checkBorders();
    }

    abstract void checkBorders();

    void move() {
    pos.add(vel);
    angle += angularVel;
    }

    abstract void display();
    }

    class Asteroid extends AbstractMover implements Hitbox {
    static final float maxVelMag = 3;
    static final float maxAngularVel = 0.04;
    static final int minHitbox_r = 15;
    final int hitbox_r;
    final int vertices = int(random(10, 15));
    final float[] offsets;

    Asteroid(float x, float y, float vx, float vy, float angularVel) {
    this(x, y, vx, vy, angularVel, int(random(15, 50)));
    }

    Asteroid(float x, float y, float vx, float vy, float angularVel, int hitbox_r) {
    super(x, y, vx, vy, 0, angularVel);
    offsets = new float[vertices];
    for (int i = 0; i < offsets.length; i++)
    offsets[i] = random(-15, 15); // vertices' offsets for creating asteroids' characteristic shape
    this.hitbox_r = hitbox_r;
    }

    @Override
    PVector getPos() {
    return pos;
    }

    @Override
    int getHitbox_r() {
    return hitbox_r;
    }

  2. Politik Games Avatar

    He starts the actual game at 22:55 if you wanna skip to it

  3. Pedro Et Cetera Avatar

    why are parts of the intro blurred?

  4. suhnshaiene Avatar

    I've had a lot of ads about Udemy coding courses lately, so when the snake game came up I assumed it was from looking into those. Targeted ads, you make me uncomfortable, but in this case you done good.

  5. jackstrapp91 Avatar

    44:10 Because array.forEach is horrible in therms of performance. Find something else or do your own tiny forRainbow loop πŸ˜‰ using array or number as parameters (to be able to loop through array or just for n times). That would be way better.
    But of course, it'll always be better to use vanilla javascript for the viewers to understand better πŸ™‚

  6. Darren Hundt Avatar

    Can't believe I just found this channel. It's so fun. Watch all videos at 2x or 2.5x speed so I kinda have a warped impression of your personality. Hints of Charlie from Always Sunny.

  7. MrOmniscient11 Avatar

    I'm loving the overzealous censoring of everything related to the contested trademark-y stuff… you even blurred your face out in case someone could lip-read you saying it! πŸ˜€ Genius πŸ˜€

  8. Juan Carlos Oropeza Avatar

    Why the camare shut off?

  9. Juan Carlos Oropeza Avatar

    Where can we find the lyrics from the intro? I understand most of it but I miss some phrases there.

  10. JLMPL Avatar

    This intro nailed it!

  11. I murder titans and scrub the f*ck out of floors! Avatar

    Why is your logo always blurred in the intro?

  12. Skankhunt42 Avatar

    daniel u can sing really well =)

  13. All Seeing Eye Avatar

    Looking forward to your new channel 'Kids of Degaussian Street' πŸ˜›

  14. Cap Archer Avatar

    Daniel taught me javascript yes, but he also taught me how to love the cringe.

  15. Nincadalop Avatar

    So just a few questions: Why should I use Processing? Who is this for? and What are it's limits?

  16. NihkzMods Avatar

    Can u do a video just like these but with c# and making a form tool thing

  17. camoogoo Avatar

    Every time you double the image resolution you are increasing the operations by 16 not 4. (n^4)/2.
    100px = 50 million, 400px = 12,800 mill. Your 400 image would take you close to 4 mins if the 200 one took 14 seconds.

Leave a Reply

Your email address will not be published. Required fields are marked *