CCLab ProjectB_Web Draft

Project Title: Beyond the Stellaris

Link:https://n-a-e-s.github.io/CCLab-Strix-Local/Star_Field/index

Descripition: The project mainly aimed to provide a web layout draft for Project B. Thu I built the layout with three main sites and a transferring CG. The first layer is set for the cover(which comes from the game Star Field.) and menu choices. The Second layer lies in the performance of the game, which is currently still in processing. Thus, I simply used a relative demo as a placeholder for the real game.  The same works for the reading material part in the third layer where there shall be a letter and operation instruction for those who live a thousand years later.  After those three layers is a transferring CG that connects all the layers. The CG is designed as a set of stars flashing towards the user,  imitating that they are going through an FTL travel.

Code:

For the whole project’s code, please visit my GitHub to accesshttps://github.com/N-A-E-S/CCLab-Strix-Local/tree/main/Star_Field

The Code mainly consists of 5 HTML files and a CSS file. Due to the concern of adjustability, I moved several style codes from independent CSS files to combine them with their HTML files. The major issue here I encountered was how to count the time and jump to a new layer after the transferred CG was played. Eventually, I used codes like

function redirect() {
window.location.href = ‘gamepage.html’;
}

setTimeout(redirect, 3000);

to solve the problem. 

Also, I attached some degree of flex CSS to the project.

Takeaway/Future improvement

  1. The second layer is a bit too pale and needs more decoration and instruction.
  2. The third layer needs more real content.
  3. The transfer between layers and transfer CG is way too straight, a little fade-in/fade-out would be nice. 
  4. The position of buttons can be optimized.

CCLab Project B Proposal

Project Working Title: Beyond the Stellaris—— An Odyssey of Major Tom

Project Description: Beyond the Stellaris is a virtual game in which the player is allowed to explore various unvisited planets in a mysterious stellar system or even more. The game aimed to provide users with 2 layers of interface: the stellar system, and the planet after landed. In general, the player may choose to land on a particular planet in the current system or initiate the FTL jump to a new system. After landing, the player may get a chance to see the breathtaking outer-space landscape, and fascinating new life forms,  which are all randomly generated via a pre-setted library of potential elements.

As planned, the system layer of the interface will be set from the perspective of the spaceship while the player serves as the pilot. The character will be under the players’ control once the ship lands on one of the planets.

The project is inspired by the so-called “NASA Punk” art style, which is promoted by the game Star Field produced by Bethesda Studio and includes a wide range of artworks, such as Space Oddity by David Bowie and movies like Interstellar and The Martian. A major characteristic of these kinds of art is the eulogizing of the exploration spirit of mankind, which is partly owing to the infection of space racing during the Cold War era. Such a “golden age” where all superpowers on the earth focused on pushing the frontier of human beings seems quite attractive to Sci-Fi lovers, especially in an era where everyone is living in a total mass of the vortex of postmodernism. Anyway, space might have already become a familiar place for our descendants after 1k years. Still, the further one goes, the less joy of first sight one may have. Pure enthusiasm for exploration may face its challenge along with the commercialization of space flight. That’s the reason why I would like to send those living in 1k years later a relatively naive imagination of outer space, to invoke their desire towards exploration and remind them of their old days when they stared at the night sky, imagining what was beyond the sky of the SOL-III.

Link to the slide:https://docs.google.com/presentation/d/1nU1OxAUMt4VBZ3k9gWSgpO9dl21iXUXAHsaJQPm1lSI/edit?usp=sharing

 

CCLab project- Particle world

Project title: Bubble Shooting

Link to the project:https://n-a-e-s.github.io/CCLAB-particle-homework/index.html

Brief Description and Concept: The project is a small game in which the player controls a character to shoot down falling bubbles from the ceiling to earn points while keeping the character away from the bubbles. The major operation users conduct is moving the character via using WASD buttons and shooting different types of bullets.

Visual Documentation: 

Coding: 

// CCLab Mini Project - 9.R Particles Template

let NUM_OF_PARTICLES = 30; // Decide the initial number of particles.
let bullets = [];
let particles = [];
var total_points = 0;
fireBreak = false;
fireBreakTime = 0;
let yoff = 0.0;
function generateNoiseColor() {
  let r = noise(yoff) * 255;
  let g = noise(yoff + 5) * 255;
  let b = noise(yoff + 10) * 255;
  yoff += 0.005;
  return color(r, g, b);
}
class Player {
  constructor(x, y) {
    this.x = x;
    this.y = y;
    this.xspd = 0;
    this.yspd = 0;
    this.dir = 1;
  }
  display() {
    push();
    translate(this.x, this.y);
    scale(this.dir, 1);
    noStroke();
    rectMode(CENTER);
    fill(30);
    rect(-7.5, 0, 55, 50);
    rectMode(CORNER);
    fill(60);
    rect(-20, -10, 20, 30);
    rect(-20, -10, 25, 10);
    rect(-20, -10, 30, 5);
    rect(-50, -5, 15, 15);
    rect(-45, -15, 10, 15);
    rect(20, -5, 15, 15);
    rect(20, -15, 10, 15);
    rect(-35, -45, 5, 10)
    fill(65);
    rect(-30, -50, 55, 30);
    fill('gold');
    rect(-30, -20, 5, 5);
    rect(-25, -15, 5, 5);
    rect(-20, -10, 5, 5);
    rect(-15, -5, 5, 5);
    rect(-10, 0, 10, 5);
    rect(0, 5, 10, 5);
    rect(10, 10, 5, 5);
    rect(15, 15, 5, 5);
    rect(-50, 10, 15, 5);
    rect(20, 10, 15, 5);
    fill(0);
    rect(-5, 25, 5, 5);
    rect(0, 30, 5, 5);
    rect(-10, 30, 5, 5);
    rect(5, 35, 5, 20);
    rect(-15, 35, 5, 20);
    rect(10, 50, 40, 5);
    rect(-50, 50, 40, 5);
    rect(45, 40, 5, 10);
    rect(35, 35, 10, 5);
    rect(25, 30, 10, 5);
    rect(20, 25, 10, 5);
    rect(-50, 40, 5, 10);
    rect(-45, 35, 10, 5);
    rect(-40, 30, 10, 5);
    rect(-35, 25, 5, 5);
    rect(-35, -25, 5, 5);
    rect(-45, -20, 10, 5);
    rect(-50, -15, 5, 10);
    rect(-55, -5, 5, 20);
    rect(-50, 15, 15, 5);
    rect(-35, 0, 5, 15);
    rect(-40, 0, 5, 5);
    rect(-25, -20, 5, 5);
    rect(-20, -15, 30, 5);
    rect(10, -20, 20, 5);
    rect(30, -20, 5, 15);
    rect(35, -5, 5, 20);
    rect(20, 15, 15, 5);
    rect(15, 0, 5, 10);
    rect(20, 0, 5, 5);
    rect(-35, -50, 5, 5);
    rect(-30, -60, 5, 10);
    rect(-25, -65, 5, 5);
    rect(-20, -70, 15, 5);
    rect(-10, -75, 15, 5);
    rect(5, -70, 5, 5);
    rect(10, -65, 5, 5);
    rect(15, -60, 5, 5);
    rect(20, -55, 5, 10);
    fill(30);
    rect(10, 40, 35, 10);
    rect(10, 35, 25, 5);
    rect(10, 25, 10, 5);
    rect(-45, 40, 30, 10);
    rect(-35, 35, 20, 5);
    rect(-30, 25, 10, 5);
    rect(-40, -15, 5, 5);
    rect(20, -15, 5, 5);
    rect(-30, -50, 50, 5);
    rect(-25, -55, 45, 5);
    rect(-25, -60, 40, 5);
    rect(-20, -65, 30, 5);
    rect(-5, -70, 10, 5);
    fill(80);
    rect(-25, -60, 5, 5);
    rect(-20, -65, 10, 5);
    fill(60);
    rect(5, 30, 20, 5);
    rect(0, 25, 10, 5);
    rect(-30, 30, 20, 5);
    rect(-20, 25, 15, 5);
    rect(-20, -60, 5, 5);
    rect(-10, -65, 5, 5);
    rect(-5, -70, 5, 5);
    fill('gold');
    rect(-15, -45, 15, 5);
    rect(-10, -40, 15, 10);
    rect(-15, -30, 15, 5);
    rect(15, -45, 10, 5);
    rect(10, -40, 10, 10);
    rect(15, -30, 10, 5);
    pop();
  }
  update() {
    if (keyIsPressed) {
      switch (key) {
        case 'w':
          //if (this.y > 50) {
          this.yspd = -10
          break;
        //}
        case 's':
          this.yspd = 1;
          break;
        case 'a':
          this.xspd = -5;
          this.dir = -1;
          break;
        case 'd':
          this.xspd = 5;
          this.dir = 1;
          break;
      }
    }
    if (this.y >= 600 && !(keyIsPressed && key == 'w')) {
      this.yspd = 0;
      this.y = 600;
    }
    else {
      if (this.y < 600) { this.yspd += 1; } } if (this.x >= 0 && this.x <= width) {
      this.x += this.xspd;
      this.y += this.yspd;
    }
    this.xspd = 0;
  }
  death_dectection() {
    for (let i = 0; i < particles.length; i++) {
      if (dist(this.x, this.y, particles[i].x, particles[i].y) < particles[i].dia / 2 + 50) { return true; } } return false; } } class bullet { constructor(x, y, color) { this.x = x; this.y = y; this.startX = x; this.startY = y; this.xspd = 0; this.yspd = 0; this.color = color; } update() { this.x += this.xspd; this.y += this.yspd; } display() { push(); translate(this.x, this.y); if (this.color == 'blue') { noStroke(); fill(0, 0, 255); rect(0, 0, 10, 10); if (dist(this.x, this.y, this.startX, this.startY) > 60) {
        for (let i = 1; i <= 10; i++) { fill(i * 20, i * 20, 255) rect(-i * this.xspd * 0.8, -i * this.yspd * 0.8, 10 - 0.2 * i, 10 - 0.2 * i); } } } else { if (this.color == 'red') { noStroke(); fill(255, 0, 0); rect(0, 0, 5, 5); if (dist(this.x, this.y, this.startX, this.startY) > 60) {
          for (let i = 1; i <= 10; i++) {
            fill(255, i * 20, i * 20)
            rect(-i * this.xspd * 0.8, -i * this.yspd * 0.8, 5 - 0.2 * i, 5 - 0.2 * i);
          }
        }
      }
    }
    pop();
  }
  hit_detection() {
    if (this.color == 'blue') {
      this.range = 10;
    }
    else {
      this.range = 3;
    }
    for (let i = 0; i < particles.length; i++) {
      if (dist(this.x, this.y, particles[i].x, particles[i].y) < particles[i].dia / 2 + this.range) {
        point = particles[i].value;
        particles.splice(i, 1);
        i--;
        total_points += point;
      }
    }
  }
}

class Particle {
  // constructor function
  constructor(startX, startY) {
    // properties: particle's characteristics
    this.x = startX;
    this.y = startY;
    this.xspd = random(0, 0.8);
    this.yspd = random(0.5, 2);
    this.dia = random(10, 30);
    this.dir = 1;
    this.value = int(map(this.dia, 10, 30, 0, 10));
  }

  // methods (functions): particle's behaviors
  update() {
    // (add) 
    this.x += this.xspd * this.dir;
    this.y += this.yspd;
  }
  display() {
    // particle's appearance
    push();
    translate(this.x, this.y);
    noStroke();
    fill(generateNoiseColor());
    circle(0, 0, this.dia);
    pop();
  }
  applyWind() {
    if (mouseX < width / 2) { this.dir = 1; } else { this.dir = -1; } } stop() { if (this.y >= height - 10) {
      this.yspd = 0;
      this.xspd = 0;
    }
  }
}
function preload() {
  myfont = loadFont('MZPXorig.ttf');
}
function setup() {
  let canvas = createCanvas(800, 800);
  canvas.parent("canvasWrapper");
  pl = new Player(width / 2, height / 2);
  // generate particles
  for (let i = 0; i < NUM_OF_PARTICLES; i++) {
    particles[i] = new Particle(random(width), random(-height, 0));
  }
}
function draw() {
  background(255, 100, 100);
  textFont(myfont);
  // update and display
  for (let i = 0; i < particles.length; i++) { let p = particles[i]; p.applyWind(); p.stop(); p.update(); p.display(); if (p.y >= height - 10) {
      particles.splice(i, 1);
      i--;
      p.y = random(-height, 0);
    }
  }
  if (particles.length == 0) {
    for (let i = 0; i < NUM_OF_PARTICLES; i++) { particles[i] = new Particle(random(width), random(-height, 0)); } } if (mouseIsPressed && !fireBreak) { n_bullet = new bullet(pl.x, pl.y, 'blue'); n_bullet.xspd = 10 * (mouseX - pl.x) / dist(pl.x, pl.y, mouseX, mouseY); n_bullet.yspd = 10 * (mouseY - pl.y) / dist(pl.x, pl.y, mouseX, mouseY); bullets.push(n_bullet); fireBreak = true; } if (keyIsPressed && key == ' ' && !fireBreak) { n_bullet = new bullet(pl.x, pl.y, 'red'); n_bullet.xspd = 10 * (mouseX - pl.x) / dist(pl.x, pl.y, mouseX, mouseY); n_bullet.yspd = 10 * (mouseY - pl.y) / dist(pl.x, pl.y, mouseX, mouseY); bullets.push(n_bullet); spd = createVector(mouseX - pl.x, mouseY - pl.y).normalize().mult(10); spd.rotate(PI / 6); n_bullet2 = new bullet(pl.x, pl.y, 'red'); n_bullet2.xspd = spd.x; n_bullet2.yspd = spd.y; bullets.push(n_bullet2); bullet3 = new bullet(pl.x, pl.y, 'red'); spd.rotate(-PI / 3); bullet3.xspd = spd.x; bullet3.yspd = spd.y; bullets.push(bullet3); fireBreak = true; } if (fireBreak) { fireBreakTime++; if (fireBreakTime >= 20) {
      fireBreak = false;
      fireBreakTime = 0;
    }
  }
  for (let i = 0; i < bullets.length; i++) { bullets[i].update(); bullets[i].display(); if (bullets[i].x > width || bullets[i].x < 0 || bullets[i].y > height || bullets[i].y < 0) {
      bullets.splice(i, 1);
      i--;
    }
    else {
      bullets[i].hit_detection();
    }
  }
  pl.update();
  pl.display();
  if (pl.death_dectection()) {
    textSize(50);
    text("Game Over", width / 2 - 100, height / 2);
    textSize(40);
    noLoop();
  }
  textSize(40);
  text("Score: " + total_points, 10, 50);
}

  

Coding Description : The code can be divided into several parts:

Initialization: The code initializes variables and constants, such as the number of particles, an array to store bullets, and an array to store particles.

Player class: In this part, the code creates a character that represents the player. The class mainly consists of three parts: Drawing, moving, and collision detecting, which display the figure and allow the user to move it with the keyboard when it’s alive.

Bullet class: In this part, the code allows the player to shoot 2 kinds of differnt bullets: a bunch of big blue bullet like a rifle or 3 small bullet like a shot gun. They are reperesneted in different colors.

Particle class: In this part, the code generates falling bubbles with a random diameter. The value of such a object also depends on the size. Also the winds system is attached.

Setup Function: In the setup() function, the canvas is created, and an instance of the player character is initialized at the center of the canvas. It also generates particles at random positions above the canvas.

Draw Function: The draw() function is the main game loop. It updates and displays all the elements in the game, including particles, bullets, and the player character.

Score Display: The player’s score is displayed on the screen.

Reflection: 

  1. Weapon class: It seems quite strange to have a bullet comes directly from the character. Having a rifle that points to the mouse would be better.
  2. Background music: The origin design of the character comes from a game called The Finals, which is quite famous for it’s fantasic music. It can also served as the music for this project.
  3. More details: More details can be added. For example: the bubble can be somehow like a firework after being hit.