About Me

portrait

I am currently learning interaction design, and I dived into this domain. I have also been trying to apply what I have learned to create new things.

I like interactive design and front-end development. I like the web development because it can provide people with a more efficient life and a wider world. And my favorited part among the web development is the part that comes into contact with the user. I think designing apps that users can use happily makes me very proud.

I have a strong self-learning ability and I am self-motivated. I made a web game during the holiday and taught myself Django to make a leader board. I finally learned to use AWS elastic beanstalk to deploy it online. This process makes me very satisfied because I made a project that others can use. I look forward to completing more powerful projects in the future for more people to use.

Project

Main Project: Brisbane River Adventure

"The winner of Best UX Design Project of ITEE Innovation Showcase 2019"

main scene screen shot

Our project is a linear interactive education website about local history. It shows about local history by introducing people Brisbane landmark and its history through an old captain. Users will be on a boat trip above the Brisbane River listen to captain about his story and play guessing game about the local old photos. It also has personalized elements that make the user more immersive.

Part A: Design Proposal

Goals to achieve

  • Establish the theme and form of the project
  • Investigate the interaction patterns of existing websites
  • Conduct user research and create personas beased on the result
  • Create an interactive flow chart for the website and make time plan for the whole project

My Contribution:

  • Participate in the discussion and contribute ideas to the theme and form of the website
  • Conducted research on some existing linear interactive sites, including The Boat and Make Your Money Matter.
  • Planning the technology that the project may use and assigning the work content

From the beginning of the project, we assembled as the Team History Fan Club, I am the team leader and front-end developer. At the beginning of the project, we participated in the World Cafe, a creative concept exchange meeting. During the World Cafe, we found a concept of a tour of the Brisbane River to introduce landmarks, which made us feel very excited. Because the Brisbane River is one of the landmarks of Brisbane, and it has passed through the whole city, it is very suitable as a carrier to introduce local customs. We then carried out user research based on this basic concept and constructed a background story for this concept. I studied the examples of two existing interactive websites, the boat and Make your money matter, and we decided to make our project an interactive linear narrative game. Our customer base will be history lovers and visitors, and we made two personas based on our target user group.

Our team finally completed a framework, and we decided to use a linear narrative to create an old captain to lead visitors to Brisbane on the river. We call it Brisbane River Adventure, and the website is positioned as an interactive local history education website. When the ship arrives at the landmark, there will be a guessing interactive mini game proposed by old captain. Visitors will be introduced to the historical background of the place, and the user will need to guess which old photo was taken there. This inspiration comes from the guessing game I proposed at Design Exploration. We gave the game a reasonable Background, that is, it is a photo album that the old captain always has, which makes the user more sense of substitution. At the same time, we also want to add more personalized elements to the website, so that users can more fully integrate into the journey of the tour.

flow-chart

At the same time, the team members also draw the interactive flow chart according to our thoughts. In the next step, we will first make a demo, including the first chapter of the game interface, and the three steps of the forward-conversation-guess diagram.

Part B: Minimum Viable Product (MVP)

Goals to achieve

  • Create first chapter of Brisbane Tour, including story, graphic material and code
  • Create the frame of product
  • Connect to SLQ dataset
  • Conduct first round of user testing and gain feedback

My Contribution:

  • Created the fron-end pages and implemented interaction functions
  • Integrate existing graphic material resources
  • Turn UI sketches into webpage
  • Developed APIs for front-end to back-end connection to facilitate future expansion
  • Tried to use more interactions and animations in your animation to provide a better user experience

In this phase we try to make an MVP to further build our project. In this step we try to make one of the chapters to implement our main interactive content, from boating to guessing. In this chapter, the goals to be achieved are: Testing the problems in the interaction, making the site easy to use and interesting.

In this chapter, our team created the content of the first chapter of the story, the graphic materials used in the game, including the building, background, picture drawing of the captain and player characters, and the storage and transmission of back-end data.

At the same time, as the front-end developer in the group, I also tested the feasibility of some of the technologies we expected to use. This includes the use of asynchronous loading to load stories through back-end scripts. And I also try to explore the animation engines and make animations more vivid and interactive.

demo screen shot

In this step, I implemented the user's input mode, which converts the mouse wheel event into a forward distance, allowing the user to adjust their travel according to the speed of the wheel. And I tried to add a wobbled special effect to simulate the real river journey. The following code is a code that I created to simulate the ship's surface swaying with the water at rest. The logic is quite simple, but this swaying has been well received by users in subsequent user tests, which is very effective.

                        
function staticRotate(boat, boundary) {
/*
This is a function to simulate the boat swaying in water when not moving.
boat (PIXI.container): the boat container
boundary (float): the bondary for changing direction
*/
    boat.rotation += boat.rotateSpeed;
    // only rotate when head is above or below the water surface
    if ((boat.rotation * boat.rotateSpeed) > 0) {
        boat.y += boat.ySpeed;
    }
    // change direction when hit the boundary
    if (Math.abs(boat.rotation) > boundary) {
        boat.ySpeed = -boat.ySpeed;
        boat.rotateSpeed = -boat.rotateSpeed;
    }
}
                        
                    

In this chapter, we have found that our interaction is recognized by the user, and the aesthetics and color of the website are also welcomed by the user. However, the user thinks that the game interface is too small, and the chapter buttons take up too much space. The indicator word "Scroll to start" at the beginning is not clear enough. At the same time, because our photo is randomly selected from the SLQ dataset except the fixed correct answer, it has the poteintial problem that there may be multiple correct answers.

In the final product, we are ready to solve these problems, and to build the functions we have planned.

Part C: Final Product

Goals to achieve

  • Finalising functions including personalisations, gallery, user-problem report and full contents
  • Settle down the 4 landmarks of Brisbane as our tour chapters
  • Create corresponding graphic materials and storys
  • Conducting furter user evaluations

My Contribution:

  • Created home page - including input nickname and select avatar
  • Integrate existing graphic material and text resources
  • Adjusted UI layout based on user feedback
  • Created a user report and other features and recorded an update log on the website about the page

In this phase we have further refined our project based on our previous progress and added story content to other chapters. Because of the time problem, we have to shorten the six chapters of the previous plan to four chapters. For this we can have time to make more beautiful graphic materials.

At the same time, I also created a home page for collecting user information according to the plan, including entering a username and selecting avatar. I used CSS to transform the form into a ship ticket, which satisfies the function and allows the user to get the feeling of entering the story when entering the website.

ticket page screenshot

We finally selected Toowong, Milton, Queenstreet and New Farm as four of Brisbane's iconic attractions along the Brisbane River, and selected four famous buildings here to create graphics and its story with old captain.

On the other hand, we value the feedback from the users. We have modified the chapter buttons to the side, so the game screen has gained more space. At the same time, we have added a bug report function, which will automatically fill in the chapter and image link to inform developers to adjust the photo blacklist and enhance the user experience.

new UI after change

The new notification have also been redesigned, the way of input is specifically to remind the user to use the mouse wheel to slide. Because in the previous test, the user expressed confusion about how to continue in the color-guessing game. So after the end of the guessing game, there will be another reminder.

new notification

As the front-end developer, I keep tring to improve user experience through creating better interaction animations. I used a smoother movement to make the user live a smoother experience while the boat is moving forward. In the old version, script simply calculate the moving distance directly based on the value input by the user, but the animation can be shaking when the user’s input value is very small. In the new function, the boat will move to the target position input by the user at a constant speed, ensuring the movement of the boat keeps smooth.

                        
//This function ensure the movement of boat is smooth anytime
//gameControl.goalPosition is calculated when user scroll the mouse wheel 
//gameControl.actualPosition is the actual postion of boat
let distance = gameControl.goalPosition - gameControl.actualPosition;
if (Math.abs(distance) > 2) {
    gameControl.actualPosition += distance > 0 ? 1 : -1;
    gameControl.boat.rotation = Math.sin(gameControl.actualPosition / 10) / 20;
    gameControl.boat.x += Math.sin(gameControl.actualPosition / 8) * 2;
                        
                    

Finally, we performed the work and achieved good results. Our products have been well received by most users. They think that the interaction of our website is easy to understand, and the art style and website design are also very comfortable. Some users have also gave us further feedback, including dialog in some chapters are too long to read.

showcase pic

Eventually our project was nominated for and won the Best User Experience Design Project in the Shcoll of ITEE Innovation Showcase 2019. We cherish this experience of creating and improving the project. This project gives us a deeper understanding of user-centered design.

Breath I/O

Breath I/O Helmet Prototype

The habit of jogging has gradually become a trend nowadays, and people also start to using a variety of wearable devices to assist their exercise. However, these wearable devices are mainly focused on providing results of exercise, and less promotion of guidance during training. Such results may make it difficult for people to relate to their specific behaviors, which makes it difficult to further improve.

Breathing during jogging is a neglected but important factor. Studies have shown that regular breathing can bring various positive effects to people during jogging.

This project aims to use a wearable device to detect people's breathing during jogging, and to guide users to practice 2:2 breathing by providing diverse feedback including visual and auditory. This project looks forward to providing users with an easy but effective breathing training guide to help users improve themselves during exercise.

Demo Video

Problem Space

Now, people are very concerned about their health, and many people have regular jogging habits. Some people have also begun to try to use wearable devices and smartphones to help record their exercise results. For example, bracelets used to record heart rate and GPS to record jogging distance and time, providing speed and calorie consumption apps, such as Running Distance Tracker +, Nick Running, etc. But these data provide only training results, without helping user to improve the process. On the other hand, breath training has been recognized by academics and joggers. O'Brien et al. (2002) pointed out that using regular breathing to drive the rhythm of running can achieve better training results. Many training websites for joggers (Airofit, 2019; Kuzma, 2019; Natmessnig, 2018) also point out that regular breathing, such as 2: 2 breathing, has a positive effect on joggers' running exercises. But for beginners, because of the lack of guidance, it takes more time and energy to complete the breath training exercises. User research shows that if someone instructs them to perform breathing training, they can enter this state more quickly. Therefore, it will be meaningful to design a wearable device to guide jogging beginners to perform breathing training for running.

User Research

Due to the social distancing, the user research is conducted online. A total of 5 online interviews were conducted.

All 4 participants with jogging experience stated that they had learned a certain breathing training method at a certain stage, and all believed that breathing training improved their jogging efficiency. One participant learned to use the nose to inhale and the mouth to exhale. Two other participants said they learned the 2: 2 breathing method, which means 2 step with one breath. Also, they will change to 1:1 breathing when speed up. 3 participants said they encountered some challenges when they started practicing breath control, such as forgetting to control in the second half of jogging. One participant stated that they was unable to adapt to the intensity of running in the early stages and was therefore unable to take care of breathing training. But they once had a coach to remind them to control breathing. They thought that the coach's reminder helped them learning faster. One participants with no jogging experience indicated that they had no knowledge of breathing training. According to them, they recalled their occasional running activities, for example, running for classes. there was no regular breathing rhythm, and they always feel exhausted after running.

When asked about the experience of using existing sports apps. One participant talked about the achievement system and leader board in the app was one of the reasons that attracted them to use the app. Another participant said they was more concerned about the performance recorded by app. Two participants indicated that they had the habit of listening to music during jogging.

Design Process

Constructing

The prototype used a microphone as an input sensor for breathing. Finally, the XC-4438 type microphone with adjustable threshold function was selected. In the early stage of the design, this project considered to collect and analyse the user's breath audio to provide users with more information to enhance the training effect. But because only the analogue signal is provided from Arduino and the microphone, it will bring great difficulties to convert it into an audio signal and then analyse it. So this idea was abandoned. Finally, after using median filtering to gain stable reading, the signal that exceeds the threshold is considered to be the user's exhaled breath as data input. One disadvantage of the microphone is that it is impossible to detect the user's inhalation process but considering that the user would not hold breath during exercise, this project assumes that the user is inhaling at the stage of no exhalation.

After confirming the use of 2: 2 breathing method, this project began to explore the possibility of step counting. In the early stage of exploration, this project tried to use the compass to obtain the user’s when running and shaking for step counting, but in fact, the shaking is not obvious, and the value hardly changes during the movement. Later we tried to use the tilt switch. The switch responded well when it was rocked up and down in the handheld test. When it was placed vertically, it was triggered every time it was shaken. But in fact, after testing on the human body, we found that the shaking of the running is not enough to trigger the tilt switch.

In the end we used an accelerometer. We use the change in reading caused by shaking up and down, that is, the change in z-axis as the basis for step counting. Similarly, after obtaining a stable reading using median filtering, the user is considered to have taken a new step when the reading exceeds the threshold, and the step is completed when the reading returns to the baseline. But one problem that has existed so far is that sometimes, the accelerometer will plus 2 steps after the user takes a step. In fact, the readings brought by the accelerometer are far more complicated than expected and may require further improving.

As mentioned above, the output method of the device is finally determined to be a display suspended at the upper right of the user's field of view.The final design is presented in image below.

Circuit diagram

The content presented on the display is considered can be difficult to read the text during running and the attention needs to be distracted on the route. The form of feedback is determined to be mainly based on images and can provide the user with the next breathing mode prediction, so that the user can be prepared. Finally, we designed a line chart to make it easier for users to notice the next breathing direction. And let it disappear as the feedback of unstable breathing rhythm as image below.

Circuit diagram

Interaction Paradigm

The figure below presents an example of interaction between the user and the system in a single use.

Circuit diagram

Because the helmet uses 2: 2 breathing method, the breathing frequency needs to be matched with the step. Therefore, the data input includes the user’s step frequency and breathing. After each input is received, the helmet will determine whether the exercise conforms to the breathing method in the background. If the breathing matches, the display will show breathing guide diagram of the next 4 steps is presented; if it does not match, the text requiring the user to adjust the breathing is presented on display.

The user maintains the breathing rhythm of his running through the guide map of breathing training to achieve the better training effect. The visualisation of the line chart allows users to predict their breathing phase in advance. At the same time, users can get feedback when their breathing becomes chaotic to reduce their attention pressure on their own breathing.

Breathing is divided into two stages: exhalation and inhalation. Because the microphone can only detect exhalation, the helmet always taking first exhales as start point after user adjustment for display guidance to achieve the best presentation effect. After the user uses the button again after the end, the device ends the training mode and presents the statistical results of this training. By comparing the result, users can understand if they have made improvement on jogging breathing training.

References

Airofit. (2019). How to breathe when running and strengthen your performance. Airofit. https://www.airofit.com/blogs/all-blog-posts/how-to-breathe-when-running-and-strengthen-your-performance

Kuzma, C. (2019). Breathing Techniques—How to Breathe While Running. Runner’s World. https://www.runnersworld.com/training/a20822091/running-on-air-breathing-technique/

Natmessnig, H. (2018, March 6). How To Breathe Properly While Running. Runtastic Blog. https://www.runtastic.com/blog/en/how-to-breathe-properly-while-running/

O’Brien, J. (2002). Running and Breathing. Yes International Publishers.

Graphic Design

portfolio screenshot

During my master's degree, I took a graphic design course, a vector graphic design course. During this course I completed four categories of graphic design topic, including just the fact, info graphic, design challenge and the final graphic design portfolio typographic design. Among them, just the fact is a single data-driven graphic design task, while info graphic is a large-scale design task with the theme of complex data set visualisation.

In the course I have completed several works that I am satisfied with. In this section I will explain my design justifications.

Just the fact example

just the fact

Fact:

105: The percentage of Australia's population in 1988 (16.6 million) compared to visitors of Brisbane's World Expo '88 (15.8 million) in the same year.

From:

ExpoMuseum. (n.d.). Expo '88, Brisbane, Queensland, Australia. Retrieved from expomuseum.com/1988/. PopulationPyramid.net. (n.d.). Population Pyramids of the World from 1950 to 2100. Retrieved from populationpyramid.net/australia/1988

Justification:

I decided to use Circle Packing figure (The Data Visualisation Catalogue, n.d.) to express this fact comparing two different number of people. Expo is a famous abbreviation for the Universal Exposition. It will be interesting to change the letter O into the pattern. The figure itself is a Circle Packing figure that two different circle overlapping together to show the area of small circle accounts for the big circle. The big circle is 105% of the area of the small circle. I used orange as the main colour, which idea came from the theme colour of logo of World Expo 1988. After that I choose an analogous colour as in green and with the same high brightness but much less saturation, to keep two circle harmony but clearly divided. For background I simply use dark grey, which can cause a strong contrast with bright figure and text, to emphasis the main message.

I placed the main pattern in the centre, because the main figure is text, so I decided to show the other words as annotation rather than a title, using two dashes to connect the big circle and the small circle. To keep the weight of the whole picture, I put one half of annotation on top, and another half to the bottom. The population annotation including a conclusion message of “105%”. Considering that the reading order is from top to bottom, I decided to put this one below. Moreover, this sentence is longer and putting it below will make the picture more stable.

I picked the typeface cocogoose family (Zetafont, 2014) for my design. This typeface has thicker letters and a very rounded letter “O”, which can be easier for reader to associate the figure and the letter O. This font fits nicely with the figure, so I think this font is the right choice.

Infor graphic

info graphic

Data source:

Australian Bureau of Statistics. (2018). 4517.0 - Prisoners in Australia, 2018. Retrieved May 19, 2019 from abs.gov.au

Justification:

The original data is complex, so I try to present complex but important information in as many dimensions as possible on a single graph. I choose to use the crime as the main category, divide the crime into bubbles, and use the area of the bubble to indicate the number of crimes. The coordinates corresponding to the centre point of each bubble are two time-related variables, the average age of imprisonment and the average age of crime. For this data, I think the second crime rate is also an important reference, so I choose to It is placed above the title as a new dimension.

I tried to assign the colour of each bubble to the highest possible degree of discrimination so that there is enough contrast between them. This also allows me to present the number of criminals in each state and the proportion of each crime in the form of a column.

Finally, I tried to add a legend in the lower right corner to make the graphics better understood.

Design challenge

design challenge

Design topic:

The challenge is to draw a suburb of Brisbane as a tourist advertisement in the style of an old-time railway poster. The required 5 colours maxium. All graphics need to be drawn by myself.

Justification:

The suburb where I live is St Lucia, and the most famous place in St Lucia is probably the street corner near St Lucia Supermarket. And my favorited thing about this place is how the sunset glows over it. So, I drew this poster with the inspiration of a photo I took before to express my deepest impression of St Lucia.

The focus of the picture is sunset glow, so I illustrated the sunset in a large area in the sky and highlighted the impression of the glow of the sunset on the road. Below the picture, from left to right are supermarkets itself, the panels at the entrance of supermarkets, roads, low walls and other townhouses. I noticed a feature of vintage posters is the abstraction of some objects but retaining complex contours. Because the house is normal for tourism tracking, so I abstracted them into black shadow. But in order to make the picture more layered, I lighted the low wall. In order to balance the supermarket on the left, a street sign was placed on the right side. In order to increase the dynamic effect of the picture, I placed a rider near the street sign who was riding a bicycle to prepare to cross the road. Finally, I chose to use a white frame to enhance the vintage feeling of the poster.

This picture uses a total of 5 colours. The sunset glow itself is deep orange (#EA5514), a colour with high saturation and passion. To make the picture harmony, I use a light orange (#F8B62D) as an analogous colour to set off the bright colours of the setting sun. Then I chose a bleak dark blue (#0857A2) as complementary colour to represent the sky in the late night while emphasis the sunset glow more. In order not to increase the complexity of the picture, I chose white (#FFFFFF) for the bright side of the ground, and black (#000000) for the dark side. Finally, order to emphasize the afterglow of the sunset, I exaggeratedly painted the ground as the same colour as the sunset to enhance the impact.

After I made multiple adjustments, I finally chose Ebrima, a sans serif font from the system. Because I found that the fonts of vintage posters are often sans serif and a little vertical font, or handwriting font for the title. But because my poster background is a bit messy, yet shortening the sunset clouds will cause the sunset to become less prominent, so I chose to use the simple sans serif font to balance the complexity of the background. Finally, I chose to emphasize the focus of the picture again with a small word on the subtitle.

Bubble Shooter

Bubble Shooter

Bubble Shooter is an online mini-game that I developed during my vacation. It was developed based on PIXI.js engine and used some open source art materials. This game is loved by my classmates and friends after it went online. There were 82 people online at peak.

Although the project was originally based on interest, it also launched a lot of new features based on the user experience after the users played. For example, the more balanced colour of the ball and the function of the leader board. At the same time, I also intend to add the function of the function ball.

The project is temporarily offline due to the free trial of AWS is expired. May come back on Firebase in the future.

Bubble Shooter is a pure web game based on PIXI.js animation engine. PIXI.js is a high-performance canvas rendering engine suitable for making h5 games. This project was originally a project for me to practice JavaScript, and making a game is defiantly an interesting way to do it. There are three main difficulties in this project. The first is that converting the position of the mouse pointer on the page and the rotation of the launch wheel. The second is to let the launched ball just be placed in the certain gap. The third difficulty is that to determine which balls need to be clear after user launching. Finally, I found the answers to these three questions.

1st challenge: rotating the wheel

In fact, to rotate the launch wheel is the simplest of the three challenges, this is a trigonometric conversion problem and I used arctangent to calculate this. But another problem is that the ball and the wheel are two separate objects. So, the ball is actually a round movement rather than rotation. To do this, I abstract the position of the mouse into a hypotenuse from the origin, and then according to the hypotenuse and the ratio of the length of the screen to convert the position of the ball.

                    
function wheelMove(mouseX, mouseY) {
    //calculate the degree of wheel rotating
    turn = Math.atan2(mouseX - appWidth / 2, appHeight - mouseY);
    //the range of rotation
    let turnLimit = 0.9;
    if (turn > turnLimit) {
        turn = turnLimit;
    } else if (turn < -turnLimit) {
        turn = -turnLimit;
    }
    //calculate the position of the ball, by calculating the proportion of size between canvas and entire page
    if (turn < turnLimit && turn > -turnLimit) {
        let times = Math.sqrt(
        Math.pow((mouseX - appWidth / 2), 2) + Math.pow((appHeight - mouseY), 2)
        ) / 128;
        ballX = (mouseX - appWidth / 2) / times + appWidth / 2;
        ballY = (mouseY - appHeight) / times + appHeight;
    }
}
                    
                

2nd challenge: Put the ball in that gap

Although launching a ball is a simple task, and we only need to change the coordinates of the ball at a fixed refresh rate and change the horizontal speed to a negative number at the boundary. But in fact, the angle of the ball launching is random, and the ball may fly to any position, making the canvas very messy.

messy canvas

To make the bubble dragon playable, it is necessary to place the ball fired by the player to the specified position, and then it is possible to process the same colour. I came up with an alternative solution for this. There is an important attribute in PIXI.js that is visible. When the game starts, script generate the ball on the full screen, but only the first 3 rows are visible. When the ball is launched, first script will determine whether it collides with a visible ball and return the line number of hit point. After the collision, it searches for the position of the invisible ball closest to it. At this point, I directly replace the invisible ball with launched ball. This alternative method solves this problem very easily.

                    
function findHitLine() {
/*
this is the function find which line does the launched ball hit and return the line number
if no hit happens, return -1
*/
    for (let i = 0; i < totalBalls.length; i++) {
        if (totalBalls[i][0].y - launchBall.y < 32 && totalBalls[i][0].y - launchBall.y > -32) {
        let line = totalBalls[i];
        for (let j = 0; j < line.length; j++) {
            let ball = line[j];
            if (hitTestCircle(launchBall, ball) && ball.isActive) {
            return i;
            }
        }
        }
    }
    return -1;
}

function findClosestEmpty(launchBall, lineNum) {
/*
This is the function find the closest position of the invisible ball when hit happends
Params:
    launchBall (PIXI.Spirit): the launched ball object
    lineNum (int): The line number that hit happens 
Returns: 
    close (array)[lineNum, index] : including the x, y coordinate information of the closest invisible ball. 
*/

    let close = [];
    let minDist = 512;
    //totalBalls is a 2 dimentional array including all balls on the map
    //start from frist line
    for (let i = 0; i < totalBalls[lineNum].length; i++) {
        let ball = totalBalls[lineNum][i];
        let dist = Math.sqrt(
            (launchBall.x - ball.x) ** 2 + (launchBall.y - ball.y) ** 2
        );
        if (dist < minDist && !ball.isActive) {
            close[0] = lineNum;
            close[1] = i;
            minDist = dist;
        }
    }
    if (lineNum > 0) {
        let line = totalBalls[lineNum - 1];
        for (let i = 0; i < line.length; i++) {
            let ball = line[i];
            let dist = Math.sqrt(
                (launchBall.x - ball.x) ** 2 + (launchBall.y - ball.y) ** 2
            );
            if (dist < minDist && !ball.isActive) {
                close[0] = lineNum - 1;
                close[1] = i;
                minDist = dist;
            }
        }
    }
    //if the hiting line is full, go to the next line.
    if (lineNum < totalBalls.length - 1) {
        let line = totalBalls[lineNum + 1];
        for (let i = 0; i < line.length; i++) {
            let ball = line[i];
            let dist = Math.sqrt(
                (launchBall.x - ball.x) ** 2 + (launchBall.y - ball.y) ** 2
            );
            if (dist < minDist && !ball.isActive) {
                close[0] = lineNum + 1;
                close[1] = i;
                minDist = dist;
            }
        }
    }
    return close;
}
                    
                
put in the gap solved

3rd Challenge: Finding balls need to be cleaned

This is probably the hardest challenge in this project. The solution I think of is a recursive approach. But because it needs to diverge in different directions, I chose to create an array readyToClear externally, using the feature of JavaScript that array name is just a reference. And I pass this array as an argument to the function adding all the target balls to the array. The function is mainly divided into two parts, the first part is findClear(). This function looks for the balls from 6 directions nears target ball r1, after finding the 6 balls, a judgment function findClearSub() will be called and 6 balls will be passed in the function separately. If the ball is newly added to the readyToClear array in findClearSub(), then we pass the ball back to findClear() and judge the 6 balls around it again. When all the balls are added to readyToClear, functions will stop and we found all the target balls.

                    
function findClear(r1, readyToClear) {
/*
Judging all balls in the six directions of this ball.
Params:
    r1 (PIXI.Spirit): the ball need to be process
    readyToClear (array)[PIXI.Spirit]: an array of balls need to be cleared
*/
    let row = (r1.y - 128) / 56;
    let column = Math.ceil(r1.x / 64) - 1;
    let lineType = totalBalls[row].length === 8 ? 1 : -1;

    let ballLine = totalBalls[row];
    if (column - 1 >= 0) {
        let tempBall = ballLine[column - 1];
        findClearSub(r1, tempBall, readyToClear);
    }
    if (column + 1 < ballLine.length) {
        let tempBall = ballLine[column + 1];
        findClearSub(r1, tempBall, readyToClear);
    }
    if (row > 0) {
        let topBallLine = totalBalls[row - 1];
        if (column < topBallLine.length) {
        let tempBall = topBallLine[column];
        findClearSub(r1, tempBall, readyToClear);
        }

        if (column - lineType < topBallLine.length && column - lineType >= 0) {
        let tempBall = topBallLine[column - lineType];
        findClearSub(r1, tempBall, readyToClear);
        }
    }
    if (row < totalBalls.length - 1) {
        let topBallLine = totalBalls[row + 1];
        if (column < topBallLine.length) {
            let tempBall = topBallLine[column];
            findClearSub(r1, tempBall, readyToClear);
        }

        if (column - lineType < topBallLine.length && column - lineType >= 0) {
            let tempBall = topBallLine[column - lineType];
            findClearSub(r1, tempBall, readyToClear);
        }
    }
}

function findClearSub(r1, tempBall, readyToClear) {

    if (tempBall.color === r1.color && tempBall.isActive) {
        let isIn = false;
        readyToClear.forEach(function (ball) {
            if (tempBall === ball) isIn = true;
        });
        if (!isIn) {
            readyToClear.push(tempBall);
            findClear(tempBall, readyToClear);
        }
    }
}

                    
                

Other improvements

Although this project is only an exercise, it won the praise of my friends after the launch. So I have received a lot of user feedback. In the early stage of production, I made a dark theme and drew balls graphic myself. But users think that this theme is too dark and makes people feel bad. For this reason, I chose the open source material of the Christmas ball to create a new theme, which became a success.

dark theme

The picture below is the theme I made by modifing the coluor with the Christmas ball material to enhance the distinction. Ii went online at the end of last year.

new theme of game

Portfolio

portfolio screenshot

At the end of the project, I created this portfolio as a review of the course and a presentation of the work. The portfolio is created using HTML, CSS and Javascript. I design and organize the content by myself. The theme color of the portfolio is the same as the blue of our major project. The content includes self-introduction, porjects introduction and contact information.

The cover of the portfolio uses a landscape that occupies the entire page. This photo is actually a part of our project's inspiration. This photo was taken by me last year at Southbank, and it is also one of the most satisfying photographs I have in my Master degree. The font of the portfolio is Rubik, a sans serif font family. This font is easy to read but vibrant, and fits the overall style of the collection.

banner photo

The theme colour of the collection uses the same blue colour as the Brisban River Adventure, relfecting the main project. I used the plugin scrollTo, an open source scrolling plugin that allows the reader to smoothly scroll to the specified location when clicking on the top navigation bar, improving the reading experience. It is also a progressive plugin that guarantees the anchor is still working when JavaScript is disabled.Because I am a front-end engineer, it is necessary to have certain code in the folio. So I used another plugin prism, which is an open source code highlighting plugin that can display code in <code> tag in the similar way of the code editor does, to enhances the reader's experience when reading the code. At the same time, this is a very light plug-in, which is only 2kb, minimizing the reader's network speed burden.

layout on mobile

In addition, this site also takes into account the browsing experience of the mobile terminal. This portfolio uses flex box to realise complex layouts, which is convenient for switching between horizontal and vertical layout. The layout of this portfolio will be responsive to ensure normal experience on different platforms.