Midterm | Pyro Dancer Release

Game Description

Pyro Dancer is an endless-runner 2D game with heavy inspirations from notable titles, such as Castlevania and Metroid inspire the game. Paired with 8-bit sound and theme by Haynes, Pyro Dancer tries to mimic the retro feel of older games.

TOP |Castlevania -Grimoire of Souls- Official Website | KONAMI

Castlevania.

The player assumes the role of a knight, invading the evil castle. Upon entering the castle, he is greeted by dozens of fireballs. To win the game, the player must dodge the fireball and achieve 500 score points. If the player runs out of health points before reaching the score, they will die.

Development Process.

Knight Sprite

Sketches, Ideas, Drawings!

The game uses sprites, images, and the p5 Play library. All assets used are linked in this document, please refer to it for further information.  The library is extensively used to allow better control over the sprites and performance.

In the beginning, I sketched, drew, and created a map of my code. Generally, it is split into three parts: a) Hero class, which functions as a class that generates every component of the player’s character.

class Hero {
  constructor(x, y) {
    this.x = x;
    this.y = y;
    //HEALTH
    this.heroHealth = 100;
    this.healthbar;
    //HERO
    this.hero;
    //BARRIER
    this.barrier;
    this.barrier2;
    this.barrierX = this.x;
  }

b) Fireball class, which serves as the group to generate, spawn, and display the fireball obstacles.

class Fireballs {
  constructor(x, y) {
    this.x = x;
    this.y = y;
    this.amount;
    this.fireballs = new Group();
    this.fireball;
    this.fireballAni;
  }

c) Main sketch, which encompasses both previous classes and displays the game properly. In this file, many functions initialize, check, and update the game. The game itself is split into three parts: The main menu, the Game Screen, and the Victory / Death Screen.

Main Screen

Game Screen

Death Screen

Challenges & Difficulties

Figuring out how the sprite system works in the p5 Play library was quite a challenge, however, it helped me a ton when configuring the fireball and character. But because of the way they draw sprites, this also made a huge problem when it comes to display updates.

I tried to code the game to allow fullscreen mode, but it never really worked properly. However, the game is coded so that it fits any kind of display resolution, but a manual refresh is needed to properly display the elements inside. I suspect this is mostly because of how spaghettified my code has become to the point that I could not re-arrange ways to update the display.

Conclusion

I truly enjoyed the process of making games with p5 js. It is not the best tool to make one, but it does have some unique capabilities that are interesting to explore. However, at some point, I became frustrated and named a function psychopathically:

function butcherSprites() {
  //remove all sprites
  player.hero.remove();
  obstacle.fireballs.removeAll();
  player.healthbar.opacity = 0;
  homeButton.opacity = 1;
}
Try out the game here!

p5.js Web Editor | Pyro Dancer – Release (p5js.org) [Display with Code]

Pyro Dancer – Release (p5js.org) [Windowed Fullscreen]

Week 5 Reading | To the Moon and Back from Our Eyes.

Around fifty-five years ago, Apollo 11 reached the moon and back to Earth. Interestingly, the computers used to guide the spacecraft only required 4 kilobytes of memory. While it may seem small by today’s standards, it was a super machine that allowed precise and complex calculations for the journey.

“That’s one small step for man, one giant leap for mankind.” -Armstrong

Levin presented us with findings over thirty years later on the advancements humanity has made regarding computers. With more capacity, they are now able to track things in real-time and output images that are not just static but interactive. This reminds me of the breakthrough that Apple made with its Apple Vision and Vision Pro. The device is a major display (no pun intended) of what computer vision has become. While it may seem lesser compared to our phones (with its low battery capacity and weight!), it also made me reimagine the future when these devices are common occurrences in daily lives.

Remember when the first iPhone was introduced by Steve Jobs: people made fun of touchscreens. Today, it is indistinguishable from our daily lives. Indeed, today Apple Vision is mostly perceived as redundant to our smartphones.  But unless someone took up the mantle and challenged the default, no invention would ever be made.

References

To the Moon and Back on 4KB of Memory – Metro Weekly

The Four Computers That Flew Humans To The Moon (youtube.com)

Levin, G. “Computer Vision for Artists and Designers: Pedagogic Tools and Techniques for Novice
Programmers”. Journal of Artificial Intelligence and Society, Vol. 20.4. Springer Verlag, 2006.

Midterm | Pyro Dancer

For the midterm, I plan to make a game called Pyro Dancer. It is a single-player endless runner game, where players assume the role of a knight trying to save the princess. Previous notable titles, such as Castlevania and Metroid inspire the game.

Concept

Pyro Dancer uses pixel art as its main artistic choice. I believe that this is the element that captures the experience and feeling of playing similar titles. Paired with 8-bit sound and theme by Haynes, Pyro Dancer tries to mimic the retro feel of older games.

Knight Sprite

Sketches, Ideas, Drawings!

As the name suggests, Pyro Dancer will feature a knight running through a supervillain castle (unknown for now) to save the princess. However, he is greeted by dozens of fireballs in the process.

Gameplay

Players will have to dodge the fireballs by going up or down. They also have the choice to speed up their running by pressing the D key. As the score increases, so does the difficulty.

Above a certain score, players will be greeted by stationary monsters that instantly kill them upon touching. This would balance out the difficulty and create varied gameplay, as dodging only fireballs would be boring!

To win the game, players must reach a score of 1000 and proceed to the boss battle. (It is still in development, and I am unsure whether I will have the time to code it!)

Development Process

While trying to program the game, I ran across a dilemma.

I could program things from scratch, but it will take more time and the chances of running into bugs is higher.

Or, I could use some external libraries to help me develop the game, where I could devote my time and energy to create a better game instead.

I used an external Javascript library called p5 Play to help me develop the game. The library introduces a sprite class that allows me to easily manage the characters, obstacles, and even the game environment with a built-in physics engine.

Asset-wise, I have compiled a lot of the resources in this document. Please refer to it for the assets that I use.

Programming-wise, I have laid down the basics and finished testing the library itself.

Main Menu Screen (Still in Development)


Debugging Game Screen

Hence, I only need to clean up the code and mash them all together plus adding some sound effects to make sure they are neatly packed as a game.

Concerns & Optimisms

Because of how busy and tight the deadlines are, I am concerned that I might not be able to play test the game extensively. By the end product, there might be a lot of bugs or unexpected exploits (could be a feature/mechanic too!) that would go unnoticed. However, I am optimistic that I will be able to deliver an enjoyable game in the end.

For some reason,  I could not import the p5 sketches into this WordPress without it spiraling out of control. I am posting my reference links below instead!

References

p5.js Web Editor | Pyro Dancer – Main Menu Cleaned (p5js.org)

p5.js Web Editor | Pyro Dancer – Game Screen (p5js.org)

p5.js Web Editor | Pyro Dancer – Knight Animation copy (p5js.org)

p5.js Web Editor | Pyro Dancer – Tutorial Screen (p5js.org)

Week 4 Readings – Norman Doors

Ah yes, should I pull or should I push this door? From the image, we can already tell that something is off with the door. The sign says to pull the door, yet the handle is flat. These doors are commonly referred to as Norman Doors, introduced by Donald A. Norman in his book we read this week.

When designing something, it is always best to remember the target audience. Most object designs require human senses as an input to be used. While this does sound able-ist, we should also ask ourselves the question: How would this object be used for those who require more assistance? 

People will always seek the path of least resistance. An intuitive design is always good. We can measure how good a design is by simply using our senses. If it feels ‘natural’ to use, as if it is part of our body, it means the object is well designed. Otherwise, if we stop to think about how to use the object, that means it is redundant.

I believe that the concept of affordances Norman wants us to embed in our minds is this: As a designer, we need to put ourselves in the shoes of the audience. Designers can impact the lives of its users, be it for good, or for the worse. Being able to distinguish the holes or problems in the experience of our design is an important aspect to always remember.

Week 4 Assignment – What da Names?

In week 4, we learned how to display text by loading custom fonts and manipulating CSV (Comma-Separated Values) files to visualize the contents.

I was originally working on some cool stuff (yes, very cool) by randomizing texts and using custom fonts for them. It was inspired by Typefaces of Toronto, an Instagram page that finds out the fonts used in facilities within the Toronto city. During this I found out that p5js have some limitations, that is the editor can only load specific font file types (such as those from Google Fonts) and not crazy ones like from Da Font.

However, I wanted to go even beyond just displaying text and wanted to manipulate data as well. So I tried to import some data sets from Kaggle and expected to play around with it. But for some reason, these data were not read properly by p5. I tried workarounds to see if appending them to a list would work but I could not get it to display properly and got errors regarding readableStream instead.

In the end, I opted for ChatGPT to help me generate a .csv file with this prompt:

Generate a CSV file. 50 rows, with three columns: name, year, count, for 50 random names within the year 2010 – 2024, in a random quantity between 1 – 5000, no spaces

After some workaround, here is the result that I came up with:

The result is a simple data showcase of Name, with Year in behind it, and the Quantity information under it. I utilized push() and pop() for the texts so that they are separate permutable objects. You can click to refresh the canvas.

//QUANTITY
  push();
  textSize(21);
  countMsg = "In that year, there are " + str(count[myNum - 2]) + " babies.";
  text(str(countMsg), width/2, height/2 + 50);
  pop();

While coding, I also noticed that I needed to subtract the list index by 2 for it to show properly. I am still figuring out why this is the case, but I assume it is because I loaded the header (index[0]), so the program treated it by skipping to the next index immediately.

Overall, it is a fun project. Had I not encountered many problems and gotten sick over the weekend I might have created something much more appealing. But for now, this is the very best I can do with my time.

References

Browse Fonts – Google Fonts

ChatGPT (openai.com)

 

 

Week 3 Reflection – Finding Interactivity

I thought the author was crazy. The use of informal words and phrases jumped me out of my seat (not literally), but it allowed me to picture Crawford as an author because of how expressive the whole chapter is.

Defining interactivity is hard. There is no absolute correct definition for the word that matches its meaning. Beyond his definition that interactivity is a cyclic process where two actors alternately listen, think, and speak, I believe sense is also an important process to add to the definition.

Most stuff that we call ‘interactive’, even in the lower degrees (based on Crawford’s degrees of interactivity), requires human sensory input. Without haptic feedback, some interactivity is gone. Think about phones, computers, or even toys, they require humans to touch, move, and (sometimes) break them for it to be interactive. Although this sounds very ableist, I believe that our senses count as much as the three actions to experience interactivity that Crawford seeks. That human sensory is important to add to the definition of “What is interactive?

Assignment 3 – Ramiel

In week 3, we learned arrays, functions, and object-oriented programming. Originally, I was trying to make Tetris because the concept was tied to using arrays and OOP. During practice, I encountered an error with my box() function, where the console referred to a built-in p5js box() function.

I became curious and decided to check out the reference pages. It turns out that the box() function generates a three-dimensional shape box using WEBGL. After some testing and playing around, I decided that I wanted to make a geometric shape using these simple shapes.

The concept is inspired by Ramiel from the popular show, Evangelion, a diamond-shaped being. Using rotation functions, I can achieve this look.

All Ramiel Scenes — EVANGELION:1.11 YOU ARE (NOT) ALONE. - YouTube

Ramiel. Evangelion 1.0 you are (not) alone.

I also experimented with sin and cosine functions that resulted in a particular pattern using texts for the background. I tried implementing a way to change the direction of the text wave, but it was more difficult than I imagined so I scraped the idea.

Mouse click to add more cubes, BACKSPACE to remove one.

The best part of the code that I liked is the pulsing effect for the cube using a very simple sin function. Overall, the project was fun and a challenging one that I enjoyed while experimenting with p5js.

display(){
    var pulse = this.size + sin(this.theta*1) * this.pulseAmplitude;  
    fill(0, this.objColor, 200);
    box(pulse);
    this.theta += 0.13;
  }

References & Tutorials

p5.js Web Editor | Circle Pulse (p5js.org)

p5.js Web Editor | Particle Waves (p5js.org)

reference | box() (p5js.org)

Week 2 Reading Response – Ordered Chaos

I am fascinated by Reas’ talk on generative art, particularly on how within the randomness of computer-generated images, there can be modifiers and parameters that are adjustable to ensure a desirable output.

In the talk, Reas starts by showcasing images that are generated randomly using computer codes, with them having distinct overarching themes. When I observed the images, a question struck my mind: can these images represent psychological states? Given how there are parameters we can adjust to control the ‘noise’ as Reas mentioned, then it certainly would be possible for these images to represent some kind of mental image.

When he displayed the screen, it struck me that the program used to generate the images was Processing or something similar. Because of this, I am interested to see how it can be done and if our class would discuss this topic.

Week 2 – Assignment – Eye Candy

In week 2, we learned loops. I wanted to take that further by introducing them to my animated art in Processing.

I used random to create a rainbow effect for the elements, while the waves were generated using loops. Similarly, the tiles are also generated using loops, while the colors are randomized for each tile, hence creating this gradient-ish effect.

For this assignment, I really wanted to get myself familiar with the way P5 draws each frame. To quote, I think I should simplify the codes and be creative with the limited tools I have rather than going over the top. Basically, I am opting by using optical illusions to create the art shown.

Here are the codes I used for the art:

var x;
var y;
var changeDirection;


function setup() {
  createCanvas(600, 600);
  frameRate(6);
  y = 300;
  changeDirection = false;
}

function draw() {
  background(0);

  //loop for tile grids
  for (let x = 0; x < width; x += 50) {
    for (let y = 0; y < height; y += 50) {
      noFill();
      strokeWeight(1);
      stroke(random(255));
      rect(x, y, 50, 50);
    }
  }

  stroke(255);
  strokeWeight(5);
  //loop for the rainbow waves rectangles
  for (let x = 0; x < width; x += 50) {
    fill(random(100, 255), random(1, 200), random(50, 100));
    rect(x, 0, 50, random(150), 0, 0, 20, 20);
    rect(x, 600, 50, random(-150), 0, 0, 20, 20);
  }

  //text
  textAlign(CENTER, CENTER);
  textSize(48);
  fill(255);
  stroke(0);
  strokeWeight(4);
  fill(random(100, 255), random(1, 200), random(50, 100));
  text("Synthwaves", width / 2 + 5, y + 5);
  fill(255);
  text("Synthwaves", width / 2, y);
  fill(180);
  text("Synthwaves", width / 2 - 5, y - 5);
  
  //If - Else statement to change text direction
  if(y>320){
        changeDirection=true
  }
  else if (y<=270){
      changeDirection=false
  }

  if (y>=0 && changeDirection == false){
      y=y+5
  }

  else if(changeDirection == true){
      y=y-5
  }

  
  

}

 

Assignment 1 – Self Portrait | Ahmad Hafizh

This is our first assignment for the Intro to IM Spring 2024 class. We are introduced to p5js in the class, and after messing around with it for a while, I began to grasp hold of the program.

 

The assignment focuses on creating a self-portrait using p5js. I was heavily inspired by Perry the Platypus when creating this because of the simple shape that can be translated using the program.

Perry the Platypus - Wikipedia

Perry the Platypus. Disney

The code that I used for the portrait is posted below. I am still confused about the arc shape, which requires a lot of planning before using. As you can see, the hat in my code is not perfectly hat-shaped enough. Nonetheless, this exercise encouraged me to practice using it more.

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(178, 216, 216);
  rectMode(RADIUS);
  fill(255, 234, 0);
  rect(200, 320, 100, 30, 20);

  //mustache
  rectMode(CENTER);
  fill(132, 90, 27);
  rect(200, 300, 100, 30, 20);

  //eyes
  ellipseMode(RADIUS);
  fill(255);
  ellipse(50, 200, 30, 30);
  ellipseMode(CENTER);
  fill(100);
  ellipse(50, 200, 30, 30);

  //eyes
  ellipseMode(RADIUS);
  fill(255);
  ellipse(350, 200, 30, 30);
  ellipseMode(CENTER);
  fill(100);
  ellipse(350, 200, 30, 30);

  //hat
  fill(132, 90, 27);
  ellipse(200, 120, 300, 30);
  arc(200, 50, 130, 200, -3.95, QUARTER_PI, OPEN);
}