Skip to content

Commit

Permalink
- Bumped version to 1.0.0
Browse files Browse the repository at this point in the history
- Added semantic versioning
- Added information dialog (which includes update checker)
- Added sounds
- Points are now calculated based on walls destroyed by the packet
  • Loading branch information
Timic3 committed Apr 2, 2018
1 parent afd5556 commit 692826e
Show file tree
Hide file tree
Showing 21 changed files with 205 additions and 72 deletions.
1 change: 1 addition & 0 deletions .angular-cli.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"outDir": "dist",
"assets": [
{ "glob": "**/*", "input": "./assets/images/", "output": "./assets/images/" },
{ "glob": "**/*", "input": "./assets/sounds/", "output": "./assets/sounds/" },
{ "glob": "favicon.ico", "input": "./", "output": "./" }
],
"index": "index.html",
Expand Down
51 changes: 24 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
# Breakout

This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.6.6.

## Development server

Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.

## Code scaffolding

Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.

## Build

Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build.

## Running unit tests

Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).

## Running end-to-end tests

Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).

## Further help

To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
# Hacker Breakout
Hacking themed Breakout game for school built using Angular framework. Written in Typescript, SCSS and HTML5.

## Backstory
You are trapped in a world, where cyber technology is heavily advanced. Everything is controlled by an A.I.
It won't let you leave, so all you can do is compete with others.

Everytime you break all walls, you open a door to a new level with higher security and bigger firewall,
therefore you will need higher network speeds. The packet will move faster based on the level you are in.
You only have 3 lives, but you gain a life after levelling up.

Move the bouncer (paddle) with ⬅️ and ➡️ keys on your keyboard. You can check leaderboards by clicking
on the ⭐ button on the far left. Score is based on how many firewalls you destroy.

## Download
You can download compiled project [here](https://github.com/Timic3/Breakout/releases/latest) or even better, view it in action [here](https://timic3.github.io/Breakout/)

## Compiling
* Install Node.js (includes npm too)
* Install Angular CLI with ```npm install -g @angular/cli@latest```
* Download the [latest source](https://github.com/Timic3/Breakout/archive/master.zip) of Galaxy Maze and unzip it
* Move into the same directory with command prompt and run ```npm install``` to install dependencies
* Run ```ng serve``` and open ```localhost:4200``` once it builds
* You can also build it with ```ng build``` for development build or ```ng build --prod``` for production build
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "breakout",
"version": "0.0.1",
"version": "1.0.0",
"license": "MIT",
"scripts": {
"ng": "ng",
Expand Down
3 changes: 3 additions & 0 deletions src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
<button mat-mini-fab (click)="openLeaderboard()">
<mat-icon>star rate</mat-icon>
</button>
<button mat-mini-fab (click)="openInfo()">
<mat-icon>info</mat-icon>
</button>
</div>

<canvas id="breakout" width="700" height="700"></canvas>
77 changes: 45 additions & 32 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
import { Component, AfterContentInit, HostListener } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { MatDialog } from '@angular/material';

import { HelloComponent } from './hello/hello.component';
import { LeaderboardComponent } from './leaderboard/leaderboard.component';
import { EndComponent } from './end/end.component';
import { InfoComponent } from './info/info.component';

import { AppConstants } from './app.constants';
import { AppStates } from './app.states';
import { Packet } from './classes/Packet';
import { Firewall } from './classes/Firewall';
import { Bouncer } from './classes/Bouncer';
import { Easing } from './classes/Utils';
import { Easing, Version } from './classes/Utils';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements AfterContentInit {
public static LATEST_VERSION = 'Server error';
public static OUTDATED = false;

public game: HTMLCanvasElement;
public context: CanvasRenderingContext2D;

Expand Down Expand Up @@ -48,7 +53,7 @@ export class AppComponent implements AfterContentInit {
public heart;
public helloScreen = true;

constructor(public dialog: MatDialog) { }
constructor(public dialog: MatDialog, private http: HttpClient) { }

ngAfterContentInit() {
this.game = <HTMLCanvasElement>document.getElementById('breakout');
Expand All @@ -66,6 +71,7 @@ export class AppComponent implements AfterContentInit {
this.packet = new Packet(packetX, packetY, this.bouncer, this.context);
this.then = Date.now();

this.fetchVersion();
this.initiateHelloScreen();

this.gameLoop();
Expand Down Expand Up @@ -114,7 +120,8 @@ export class AppComponent implements AfterContentInit {
// BAD AGAIN
if (AppStates.ENDED) {
AppStates.ENDED = false;
this.openEnd();
this.openEnd(AppStates.SCORE);
AppStates.SCORE = 0;
}

if (this.levelUp) {
Expand Down Expand Up @@ -161,7 +168,11 @@ export class AppComponent implements AfterContentInit {
this.packet.draw();

// UI
// TODO

this.context.font = '25px Ubuntu';
this.context.textAlign = 'left';
this.context.fillStyle = 'rgba(255, 255, 255, 1.0)';
this.context.fillText('Score: ' + AppStates.SCORE, 5, AppConstants.GAME_HEIGHT + 32, AppConstants.GAME_WIDTH);

for (let i = 0; i < Packet.health; i++) {
this.context.drawImage(this.heart, (AppConstants.GAME_WIDTH - 40) - 40 * i, AppConstants.GAME_HEIGHT, 32, 32);
Expand Down Expand Up @@ -194,6 +205,27 @@ export class AppComponent implements AfterContentInit {
}
}

fetchVersion() {
this.http.get('https://api.github.com/repos/Timic3/Breakout/releases/latest')
.subscribe(
(data: any) => {
AppStates.LATEST_VERSION = data.tag_name;
console.log('Current version: ' + AppConstants.APP_VERSION);
console.log('Latest GitHub version: ' + data.tag_name);
const compareVersions = Version.compare(AppConstants.APP_VERSION, data.tag_name);
console.log('Semantic version comparator: ' + compareVersions);
if (compareVersions < 0) {
console.log('You are using outdated version! Update here: https://github.com/Timic3/Breakout/releases/latest');
AppStates.OUTDATED = true;
}
},
(error: HttpErrorResponse) => {
console.log('An error occurred while fetching version.');
console.log('Error: ' + error.status + ' (' + error.statusText + ')');
console.log('Report to: https://github.com/Timic3/Maze/issues');
});
}

initiateHelloScreen() {
setTimeout(() => {
const dialog = this.dialog.open(HelloComponent, {
Expand All @@ -215,37 +247,18 @@ export class AppComponent implements AfterContentInit {
});
}

openEnd() {
openEnd(endScore) {
const dialog = this.dialog.open(EndComponent, {
width: '500px'
width: '500px',
data: {
score: endScore
}
});
}

cameraShake() {
if (this.shakeTickStart === -1) {
return;
}

const tick = Date.now() - this.shakeTickStart;
if (tick > this.shakeTime) {
this.shakeTickStart = -1;
return;
}

const easing = Math.pow(tick / this.shakeTime - 1, 3) + 1;
this.context.save();
const shakeX = easing * (Math.cos(tick * 0.1) + Math.cos(tick * 0.3115)) * 2;
const shakeY = easing * (Math.sin(tick * 0.05) + Math.sin(tick * 0.057113)) * 2;
this.context.translate(shakeX, shakeY);
}

// To be finished
virusPreShake() {
this.context.save();
this.context.translate(Math.random() * 20, Math.random() * 20);
}

restoreCamera() {
this.context.restore();
openInfo() {
const dialog = this.dialog.open(InfoComponent, {
width: '500px'
});
}
}
3 changes: 3 additions & 0 deletions src/app/app.constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
export class AppConstants {
// Application version
static readonly APP_VERSION = '1.0.0';

static readonly GAME_WIDTH = 1200;
static readonly GAME_HEIGHT = 700;

Expand Down
8 changes: 6 additions & 2 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

import {
MatButtonModule,
Expand All @@ -13,25 +14,28 @@ import { AppComponent } from './app.component';
import { HelloComponent } from './hello/hello.component';
import { LeaderboardComponent } from './leaderboard/leaderboard.component';
import { EndComponent } from './end/end.component';
import { InfoComponent } from './info/info.component';


@NgModule({
declarations: [
AppComponent,
HelloComponent,
LeaderboardComponent,
EndComponent
EndComponent,
InfoComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
HttpClientModule,
MatButtonModule,
MatDialogModule,
MatIconModule,
MatInputModule
],
providers: [],
bootstrap: [AppComponent],
entryComponents: [HelloComponent, LeaderboardComponent, EndComponent]
entryComponents: [HelloComponent, LeaderboardComponent, EndComponent, InfoComponent]
})
export class AppModule { }
4 changes: 4 additions & 0 deletions src/app/app.states.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@ export class AppStates {
static readonly WALLS_HEIGHT = 40;

public static NAME = 'guest';
public static SCORE = 0;

public static LATEST_VERSION = 'Server error';
public static OUTDATED = false;
}
24 changes: 23 additions & 1 deletion src/app/classes/Packet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,26 @@ export class Packet extends Drawable {
private bounces: PacketIP[] = [];
private bouncer; // Collider

private wallAudio;
private pointAudio;
private paddleAudio;

constructor(x: number, y: number, bouncer: Bouncer, context: CanvasRenderingContext2D) {
super(x, y, context);
this.bouncer = bouncer;
this.bounces.push(new PacketIP(bouncer.x + AppConstants.BOUNCER_WIDTH / 2, bouncer.y - 5));

this.wallAudio = new Audio();
this.wallAudio.src = './assets/sounds/wall.wav';
this.wallAudio.load();

this.paddleAudio = new Audio();
this.paddleAudio.src = './assets/sounds/paddle.wav';
this.paddleAudio.load();

this.pointAudio = new Audio();
this.pointAudio.src = './assets/sounds/point.wav';
this.pointAudio.load();
}

draw() {
Expand Down Expand Up @@ -62,6 +78,7 @@ export class Packet extends Drawable {
this.y = this.bouncer.y - AppConstants.PACKET_RADIUS;
this.velocityX = (this.x - this.bouncer.x - AppConstants.BOUNCER_WIDTH / 2) / 100;
this.updateAngle();
this.wallAudio.cloneNode(true).play();
if (this.bounces[0]) {
this.bounces[0].returnX = this.x;
this.bounces[0].returnY = this.y;
Expand Down Expand Up @@ -160,6 +177,8 @@ export class Packet extends Drawable {

manageWallHit(wall) {
wall.active = false;
AppStates.SCORE += 10;
this.pointAudio.cloneNode(true).play();
this.managePacketIP();

if (this.checkForWalls()) {
Expand Down Expand Up @@ -266,6 +285,7 @@ export class Packet extends Drawable {
this.hitRight = true;
// Don't bug out!
this.x = AppConstants.GAME_WIDTH - AppConstants.PACKET_RADIUS;
this.wallAudio.cloneNode(true).play();
}

if (this.y >= AppConstants.GAME_HEIGHT - AppConstants.PACKET_RADIUS) {
Expand All @@ -284,7 +304,7 @@ export class Packet extends Drawable {
if (--Packet.health <= 0) {
// Reset game
AppStates.STARTED = false;
LeaderboardComponent.saveScore(AppStates.STAGE);
LeaderboardComponent.saveScore(AppStates.SCORE);
AppStates.ENDED = true;
AppStates.STAGE = 1;
AppStates.WALLS_X = 3;
Expand All @@ -302,6 +322,7 @@ export class Packet extends Drawable {
this.hitLeft = true;
// Bug check
this.x = AppConstants.PACKET_RADIUS;
this.wallAudio.cloneNode(true).play();
}

if (this.y < AppConstants.PACKET_RADIUS) {
Expand All @@ -310,6 +331,7 @@ export class Packet extends Drawable {
this.managePacketIP(true);
// Bug check
this.y = AppConstants.PACKET_RADIUS;
this.wallAudio.cloneNode(true).play();
}

if (this.hitRight) {
Expand Down
17 changes: 17 additions & 0 deletions src/app/classes/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,20 @@ export class Easing {
return Math.sin(13 * (Math.PI / 2) * t) * Math.pow(2, 10 * (t - 1));
}
}

// Semantic versioning compare method
export class Version {
public static compare(a, b) {
const aVer = a.split('.');
const bVer = b.split('.');
for (let i = 0; i < 3; i++) {
if (Number(aVer[i]) > Number(bVer[i])) {
return 1;
}
if (Number(aVer[i]) < Number(bVer[i])) {
return -1;
}
}
return 0;
}
}
2 changes: 1 addition & 1 deletion src/app/end/end.component.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<h1 mat-dialog-title>🖤 You've lost all your lives</h1>

<mat-dialog-content>
<h4>Your score was saved.</h4>
<h4>You scored <span class="personal">{{endScore}}</span> points.</h4>
</mat-dialog-content>

<mat-dialog-actions align="end">
Expand Down
Loading

0 comments on commit 692826e

Please sign in to comment.