Galaxy Asteroids consists of a singleplayer/multiplayer and multi-screen game that looks like the old Asteroids with the Diep.io mechanics. Players will control their spaceships in a limited battlefield (the space), visible into the Liquid Galaxy system (screens), with their virtual joystick (mobile app), fighting each other in a thirsty competition in order to achieve the highest score, being what most players like.
Before installing the game, it's necessary to have some other tools installed as well.
First, make sure Node.js version 14+ is installed on the master machine by running:
$ node -v
This command should print something like v16.17.0
. In case it doesn't, install Node.js by following the 3 first steps at the link: How To Install Latest Node.js on Ubuntu 16.04.
With Node.js installed, the next tool that must be installed is pm2. Run the command below to install it:
$ sudo npm i -g pm2
Finally, make sure to have Chromium Browser installed on all machines.
Chromium Browser is usually installed into the Liquid Galaxy systems.
There's a few steps to be able to run and play the game.
First, open a new terminal and make sure you're into the HOME directory by running the cd
command.
Then, clone the Galaxy Asteroids repository by running:
$ git clone https://github.com/LiquidGalaxyLAB/galaxy-asteroids.git
Having the game in the local machine is not enough. Install it by running:
$ cd galaxy-asteroids
$ bash install.sh {password}
The {password} is the password from you system.
That's it for the installation! The game is running on the pm2 using the 8129 port.
The 8129 port can't be accessed until you reboot the machine.
All of the installation logs is kept into the ./logs
directory. Make sure to check it out if you experience any problems throughout the installation.
To be able to play the game, you must execute the open.sh
script.
To do so, navigate to the game directory by running:
$ cd ~/galaxy-asteroids
Then run the open.sh
script:
$ bash ./scripts/open.sh
To close the game, execute the close.sh
script:
$ bash ./scripts/close.sh
With the game running, open the http://<master-ip>:<game-port>/
with a mobile device to access the joystick controller.
To have a better experience, use the LG Retro Gaming application to install and play the game. You must install it by following its documentation and download the app from the Google Play Store to be able to access the joystick controller.
The project is divided into libs
, src
and index.js
:
libs/
- asteroids/
- src/
- decorators/
- interfaces/
- math/
- utils/
- abstract-component.ts
- abstract-entity.ts
- abstract-scene.ts
- abstract-service.ts
- asteroids.factory.ts
- constants.ts
- index.ts
- tsconfig.lib.json
- src/
src/
- @types/
- assets/
- fonts/
- html/
- scss/
- svg/
- ts/
- game-objects/
- some-game-object/
- components/
- entities/
- enums/
- interfaces/
- some-game-object/
- scenes/
- some-scene.scene.ts
- shared/
- components/
- entities/
- enums/
- interfaces/
- services/
- ui/
- some-ui-element/
- entities/
- enums/
- interfaces/
- some-ui-element/
- utils/
- game-objects/
- global.scss
- index.html
- index.ts
index.js
Contains the asteroids
library, which keeps all of the project main functionalities, such as entities
, components
, scenes
and services
logic and instantiating. It may be referenced as @asteroids
when importing classes, interfaces and other files.
import { AbstractEntity, Entity, IOnAwake } from '@asteroids'
Being the starting point of the application, deals with its initializing using express. Also contains all of the socket server logic.
Deals with the game initialization using the bootstrap
function, which is responsible for getting the given scene
and using it to create the game instance.
Is the entry point for keeping all of the game canvas
elements.
Contains global styles and imports from other scss
files.
Keeps almost all of the game elements and logic.
- fonts: contains all game fonts.
- html: contains all of the UI html elements. I.e.: score.
- scss: keeps the UI elements styling.
- svg: keeps all game svg images. I.e.: spaceship.
- ts: contains all of the game logic.
Keeps all the main game objects and their own components, entities, interfaces and more.
Example: game-objects/
- spaceship/
- components/
- input.component.ts
- entities/
- spaceship-slave.entity.ts
- spaceship.entity.ts
- interfaces/
- input.interface.ts
- components/
Keeps all shared/common components, enums, interfaces, services and more.
Example: shared/
- components/
- drawer.component.ts
- enums/
- player.enum.ts
- interfaces/
- player.interface.ts
- services/
- socket.service.ts
Keeps all UI related entities.
Example: ui/
- background/
- entities/
- space-background.entity.ts
- background.entity.ts
- entities/
- score/
- entities/
- score.entity.ts
- entities/
Life cycle methods are used to run code on different times on each loop.
- onAwake: called when the dependencies of some component, entity or service are resolved.
- onStart: called after the
onAwake
method at the beginning of the loop. - onDestroy: called when the entity is destroyed.
- onLoop: called on every game cycle.
- onLateLoop: called after the
onLoop
method. - onFixedLoop: called on every game physics cycle.
Services keeps a set of methods and properties that won't change while the application is running unstoppably. They extends the AbstractService
and use the @Service
decorator.
@Service()
export class MyService extends AbstractService {}
It may use other services using the services
property into the @Service
decorator and initialized it into the onAwake
life cycle method.
import { AbstractService, IOnAwake, Service } from '@asteroids'
import { SocketService } from '@/assets/ts/shared/services/socket.service'
@Service({
services: [SocketService],
})
export class MyService extends AbstractService implements IOnAwake {
private socketService: SocketService
onAwake() {
this.socketService = this.getService(SocketService)
}
}
Represents a group of behavior and properties that may be applied to one or more entities. It must extend the AbstractComponent
class and use the @Component
decorator.
@Component()
export class MyComponent extends AbstractComponent {}
A component may use another by passing the required
property. It may also use services by passing the services
properties. The required components and services must be initialized into the onAwake
life cycle method.
import { AbstractComponent, Component, IOnAwake } from '@asteroids'
import { Drawer } from '@/assets/ts/shared/components/drawer.component'
import { MyService } from '@/assets/ts/shared/services/my-service.service'
import { MyComponent } from '@/assets/ts/.../components/my-component.component'
@Component({
required: [Drawer, MyComponent],
services: [MyService],
})
export class MyComponent extends AbstractComponent implements IOnAwake {
private drawer: Drawer
private myComponent: MyComponent
private myService: MyService
onAwake() {
this.drawer = this.getComponent(Drawer)
this.myComponent = this.getComponent(MyComponent)
this.myService = this.getService(MyService)
}
}
Represents a renderable unique object/entity, such as a spaceship
, asteroid
, background
, bullet
and others.
To create an entity, the @Entity
decorator and AbstractEntity
class must be used.
@Entity()
export class MyEntity extends AbstractEntity {}
Entities use components to acquire generic behaviors: transform
, physics
, rendering
, etc. This components may be inserted into the entity decorator: @Entity
.
Also, entities may also have services passed into the decorator to be used by using the services
property. To initialize them, use the onAwake
life cycle method.
import { AbstractEntity, Entity, IOnAwake } from '@asteroids'
import { Drawer } from '@/assets/ts/shared/components/drawer.component'
import { Render } from '@/assets/ts/shared/components/renderers/render.component'
import { Rigidbody } from '@/assets/ts/shared/components/rigidbody.component'
import { Transform } from '@/assets/ts/shared/components/transform.component'
import { MyService } from '@/assets/ts/shared/services/my-service.component'
import { MyComponent } from '@/assets/ts/.../components/my-component.component'
@Entity({
components: [
Drawer,
Render,
Transform,
{
id: '__my_entity_rigidbody__',
class: Rigidbody,
},
{
class: MyComponent,
use: {
property: 'value',
},
},
],
services: [MyService],
})
export class MyEntity extends AbstractEntity implements IOnAwake {
private drawer: Drawer
private render: Render
private transform: Transform
private rigidbody: Rigidbody
private myService: MyService
onAwake() {
this.drawer = this.getComponent(Drawer)
this.render = this.getComponent(Render)
this.transform = this.getComponent(Transform)
this.rigidbody = this.getComponent(Rigidbody)
// The MyComponent component is not going to be used directly in
// the entity, we just need its behavior.
this.myService = this.getService(MyService)
}
}
Scenes are used to create a base canvas and instantiate a set of entities. They must extends the AbstractService
class and use the @Scene
decorator.
import { AbstractScene, Scene } from '@asteroids'
import { MyEntity } from '@/assets/ts/.../entities/my-entity.entity'
@Scene()
export class MyScene extends AbstractScene {
this.createCanvas({
name: 'my-scene',
mode: 'clear',
})
this.instantiate({ entity: MyEntity })
}
The Galaxy Asteroids project is licensed under the MIT license.