Updated the GameEngine

Signed-off-by: Avior <github@avior.me>
This commit is contained in:
2021-06-19 00:46:04 +02:00
parent 40f1e296af
commit 8952b61651
38 changed files with 1503 additions and 322 deletions

View File

@@ -0,0 +1,42 @@
import Component2D from 'GameEngine/Component2D'
import Vector2D from '../Vector2D'
type BuiltinCollisionTypes = 'click'
export default class BoxCollider2D {
public constructor(
private component: Component2D,
public type: BuiltinCollisionTypes | string = 'collision',
private center = new Vector2D(0, 0),
private scale = new Vector2D(1, 1)
) {}
public pointColliding(point: Vector2D, type: BuiltinCollisionTypes | string = 'collision'): boolean {
if (this.type !== type) {
return false
}
return point.isIn(
...this.pos()
)
}
public pos(): [Vector2D, Vector2D] {
const scale = this.scale.multiply(this.component.scale)
const positionCenter = this.component.origin.sub(
new Vector2D(
this.component.position.x,
this.component.position.y
)
)
const center = this.center.sum(positionCenter)
return [new Vector2D(
center.x - scale.x / 2,
center.y - scale.y / 2
),
new Vector2D(
center.x + scale.x / 2,
center.y + scale.y / 2
)]
}
}

View File

@@ -0,0 +1,25 @@
import Component2D, { ComponentState } from 'GameEngine/Component2D'
import RectRenderer from 'GameEngine/Renderer/RectRenderer'
import BoxCollider2D from '../Collision/BoxCollider2D'
import Vector2D from '../Vector2D'
export default class ColliderDebugger extends Component2D {
public constructor(component: Component2D, collider: BoxCollider2D) {
super()
this.collider = collider
const [topLeft, bottomRight] = collider.pos()
const size = topLeft.sub(bottomRight)
this.position = topLeft
this.scale = size
this.origin = new Vector2D(-(this.scale.x / 2), -(this.scale.y / 2))
this.renderer = new RectRenderer(this, {stroke: 'black'})
}
public update(state: ComponentState) {
if (state.isColliding) {
(this.renderer as RectRenderer).material = 'rgba(0, 255, 0, .7)'
} else {
(this.renderer as RectRenderer).material = undefined
}
}
}

View File

@@ -0,0 +1,14 @@
import Component2D from 'GameEngine/Component2D'
import RectRenderer from 'GameEngine/Renderer/RectRenderer'
import Vector2D from '../Vector2D'
export default class ComponentDebug extends Component2D {
public constructor(component: Component2D) {
super()
this.position = component.position
this.origin = component.origin
this.scale = new Vector2D(.1, .1)
console.log('Position of the origin point', this.position)
this.renderer = new RectRenderer(this, {material: 'red'})
}
}

View File

@@ -0,0 +1,14 @@
import Component2D from 'GameEngine/Component2D'
import RectRenderer from 'GameEngine/Renderer/RectRenderer'
import Vector2D from '../Vector2D'
export default class PointDebugger extends Component2D {
public constructor(point: Vector2D) {
super()
this.scale = new Vector2D(.1, .1)
this.position = point
console.log('Debugging point at location', point)
// this.origin = component.origin
this.renderer = new RectRenderer(this, {material: 'red'})
}
}

View File

@@ -0,0 +1,30 @@
/* eslint-disable max-classes-per-file */
import Component2D, { ComponentState } from 'GameEngine/Component2D'
import RectRenderer from 'GameEngine/Renderer/RectRenderer'
import Vector2D from '../Vector2D'
export default class TilingDebugger extends Component2D {
public constructor() {
super()
for (let i0 = 0; i0 < 10; i0++) {
for (let i1 = 0; i1 < 10; i1++) {
this.childs.push(
new CaseDebugger(new Vector2D(i0, i1)),
// new CaseDebugger(new Vector2D(i0 + .5, i1 + .5)),
// new CaseDebugger(new Vector2D(i0 + .75, i1 + .75)),
// new CaseDebugger(new Vector2D(i0 + .25, i1 + .75)),
// new CaseDebugger(new Vector2D(i0 + .75, i1 + .25)),
// new CaseDebugger(new Vector2D(i0 + .25, i1 + .25))
)
}
}
}
}
class CaseDebugger extends Component2D {
public renderer: RectRenderer = new RectRenderer(this, {stroke: 'black'})
public constructor(pos: Vector2D) {
super()
this.position = pos
}
}

View File

@@ -0,0 +1,30 @@
/* eslint-disable no-underscore-dangle */
export default class Size2D {
private _width: number
private _height?: number
public constructor(
width: number,
height?: number
) {
this._width = width
this._height = height
}
public get width() {
return this._width
}
public set width(v: number) {
this._width = v
}
public get height() {
return this._height ?? this._width
}
public set height(v: number) {
this._height = v
}
}

View File

@@ -0,0 +1,35 @@
export default class Vector2D {
public constructor(
public x: number,
public y: number
) {}
public multiply(v: Vector2D): Vector2D {
return new Vector2D(
v.x * this.x,
v.y * this.y
)
}
public sum(v: Vector2D): Vector2D {
return new Vector2D(
v.x + this.x,
v.y + this.y
)
}
public sub(v: Vector2D): Vector2D {
return new Vector2D(
v.x - this.x,
v.y - this.y
)
}
public isIn(topLeft: Vector2D, bottomRight: Vector2D): boolean {
return this.x >= topLeft.x &&
this.y >= topLeft.y &&
this.x <= bottomRight.x &&
this.y <= bottomRight.y
}
}

5
src/GameEngine/Camera.ts Normal file
View File

@@ -0,0 +1,5 @@
import Vector2D from './2D/Vector2D'
export default class Camera {
public topLeft = new Vector2D(0.5, 0.5)
}

View File

@@ -1,34 +1,35 @@
import BoxCollider2D from './2D/Collision/BoxCollider2D'
import Vector2D from './2D/Vector2D'
import Renderer from './Renderer'
export interface ComponentState {
mouseHovering: boolean
mouseClicking: boolean
mouseClicked: boolean
/**
* is it is collinding return the type of collision
*/
isColliding?: string
}
export default abstract class Component2D {
public id?: number
public renderer?: Renderer
public pos?: {x: number, y: number, z?: number, rotation?: number}
public position: Vector2D = new Vector2D(0, 0)
protected size?: number | {width: number, height: number}
public scale: Vector2D = new Vector2D(1, 1)
public collider?: BoxCollider2D
/**
* Change the origin point (default to middle)
*/
public origin: Vector2D = new Vector2D(0 , 0)
public childs: Array<Component2D> = []
public debug?: boolean
public init?(): Promise<void> | void
public update?(state: ComponentState): Promise<void> | void
public width() {
if (!this.size) {
return undefined
}
return typeof this.size === 'number' ? this.size : this.size?.width
}
public height() {
if (!this.size) {
return undefined
}
return typeof this.size === 'number' ? this.size : this.size?.height
}
}

View File

@@ -1,24 +0,0 @@
import GameEngine from 'GameEngine'
import Component2D from 'GameEngine/Component2D'
import Renderer from '.'
export default class ColorRenderer implements Renderer {
public constructor(
private component: Component2D,
private color: string
) {}
public async render(ge: GameEngine, ctx: CanvasRenderingContext2D) {
if (!this.component.pos) {
return
}
ctx.fillStyle = this.color
ctx.fillRect(
this.component.pos.x * (ge.caseSize[0]),
this.component.pos.y * (ge.caseSize[1]),
(this.component.width() ?? ge.caseSize[0]) * ge.caseSize[0],
(this.component.height() ?? ge.caseSize[1]) * ge.caseSize[1]
)
}
}

View File

@@ -1,25 +0,0 @@
import GameEngine from 'GameEngine'
import Asset from 'GameEngine/Asset'
import Component2D from 'GameEngine/Component2D'
import Renderer from '.'
export default class ImageRenderer implements Renderer {
public constructor(
private component: Component2D,
private image: Asset
) {}
public async render(ge: GameEngine, ctx: CanvasRenderingContext2D) {
if (!this.component.pos) {
return
}
ctx.drawImage(
await this.image.get(),
this.component.pos.x * (ge.caseSize[0]),
this.component.pos.y * (ge.caseSize[1]),
(this.component.width() ?? ge.caseSize[0]) * ge.caseSize[0],
(this.component.height() ?? ge.caseSize[1]) * ge.caseSize[1]
)
}
}

View File

@@ -0,0 +1,52 @@
import { objectLoop } from '@dzeio/object-util'
import GameEngine from 'GameEngine'
import Asset from 'GameEngine/Asset'
import Component2D from 'GameEngine/Component2D'
import Renderer from '.'
interface Params {
material?: string | Asset
stroke?: string
}
export default class RectRenderer extends Renderer implements Partial<Params> {
public material?: string | Asset
public stroke?: string
public constructor(component: Component2D, params?: Params) {
super(component)
objectLoop(params ?? {}, (v, k) => {this[k as 'material'] = v})
}
public async render(ge: GameEngine, ctx: CanvasRenderingContext2D) {
const position = this.getPosition()
const item: [number, number, number, number] = [
// source x
// 0 - 1.5 - -1.5
position.x * (ge.caseSize.x),
// source y
position.y * (ge.caseSize.y),
// source end X
this.component.scale.x * (ge.caseSize.x),
// source end Y
this.component.scale.y * (ge.caseSize.y)
]
if (this.material instanceof Asset) {
ctx.drawImage(
await this.material.get(),
...item
)
return
}
if (this.material) {
ctx.fillStyle = this.material
ctx.fillRect(...item)
}
if (this.stroke) {
ctx.strokeStyle = this.stroke
ctx.strokeRect(...item)
}
}
}

View File

@@ -1,31 +1,44 @@
import { objectLoop } from '@dzeio/object-util'
import GameEngine from 'GameEngine'
import Vector2D from 'GameEngine/2D/Vector2D'
import Component2D from 'GameEngine/Component2D'
import Tileset from 'GameEngine/Tileset'
import Renderer from '.'
export default class TileRenderer implements Renderer {
interface Params {
tileset?: Tileset
id?: number
}
public constructor(
private component: Component2D,
private tileset: Tileset,
private id: number
) {}
/**
* TODO: Add origin support
*/
export default class TileRenderer extends Renderer implements Params {
public tileset?: Tileset
public id?: number
public constructor(component: Component2D, params?: Params) {
super(component)
objectLoop(params ?? {}, (v, k) => {this[k as 'id'] = v})
}
public async render(ge: GameEngine, ctx: CanvasRenderingContext2D) {
if (!this.component.pos) {
if (!this.tileset || typeof this.id !== 'number') {
return
}
const {sx, sy} = this.tileset.getSourceData(this.id)
const position = this.getPosition()
ctx.drawImage(
await this.tileset.asset.get(),
sx,
sy,
this.tileset.width(),
this.tileset.height(),
this.component.pos.x * (ge.caseSize[0]),
this.component.pos.y * (ge.caseSize[1]),
(this.component.width() ?? ge.caseSize[0]) * ge.caseSize[0],
(this.component.height() ?? ge.caseSize[1]) * ge.caseSize[1]
this.tileset.width(this.id),
this.tileset.height(this.id),
position.x * (ge.caseSize.x),
position.y * (ge.caseSize.y),
(this.component.scale.x ?? ge.caseSize.x) * ge.caseSize.x,
(this.component.scale.y ?? ge.caseSize.y) * ge.caseSize.y
)
}
}

View File

@@ -1,5 +1,21 @@
import GameEngine from 'GameEngine'
import Vector2D from 'GameEngine/2D/Vector2D'
import Component2D from 'GameEngine/Component2D'
export default interface Renderer {
render(ge: GameEngine, ctx: CanvasRenderingContext2D): Promise<void>
// eslint-disable-next-line @typescript-eslint/ban-types
export default abstract class Renderer {
public constructor(
protected component: Component2D
) {}
protected getPosition(): Vector2D {
const ge = GameEngine.getGameEngine()
const realPosition = ge.currentScene.camera.topLeft.sum(this.component.position)
return new Vector2D(
realPosition.x - this.component.scale.x / 2 - this.component.origin.x,
realPosition.y - this.component.scale.y / 2 - this.component.origin.y
)
}
public abstract render(ge: GameEngine, ctx: CanvasRenderingContext2D): Promise<void>
}

View File

@@ -1,18 +1,23 @@
import GameEngine from 'GameEngine'
import { ComponentState } from 'react'
import AssetsManager from './Asset'
import Component2D from './Component2D'
import Camera from './Camera'
import Component2D, { ComponentState } from './Component2D'
export default class Scene {
public static scenes: Record<string, Scene> = {}
public background?: string
public id: string
public camera: Camera = new Camera()
private components: Array<Component2D> = []
private ge!: GameEngine
public constructor(sceneId: string) {
Scene.scenes[sceneId] = this
this.id = sceneId
}
public addComponent(...cp: Array<Component2D>) {
@@ -32,25 +37,53 @@ export default class Scene {
}
public async update() {
this.components.forEach(async (v) => {
const state: Partial<ComponentState> = {}
const width = (v.size?.width ?? 1) * this.ge.caseSize[0]
const height = (v.size?.height ?? 1) * this.ge.caseSize[1]
if (v.pos) {
const ax = v.pos.x * this.ge.caseSize[0]
const ay = v.pos.y * this.ge.caseSize[1]
state.mouseHovering =
this.ge.cursor.x >= ax && this.ge.cursor.x < (ax + width) &&
this.ge.cursor.y >= ay && this.ge.cursor.y < (ay + height)
state.mouseClicking = state.mouseHovering && this.ge.cursor.isDown
state.mouseClicked = state.mouseClicking && !this.ge.cursor.wasDown
for (const component of this.components) {
await this.updateComponent(component)
}
}
private async updateComponent(v: Component2D) {
const debug = v.debug
if (debug) {
console.log('Processing Component', v)
}
const state: Partial<ComponentState> = {}
// const width = (v.width() ?? 1) * this.ge.caseSize[0]
// const height = (v.height() ?? 1) * this.ge.caseSize[1]
if (v.collider && v.collider.type === 'click' && this.ge.cursor.isDown && !this.ge.cursor.wasDown) {
if (v.collider.pointColliding(this.ge.cursor.position, 'click')) {
state.isColliding = 'click'
}
if (v.renderer) {
await v.renderer.render(this.ge, this.ge.ctx)
}
// if (v.pos) {
// const ax = v.pos.x * this.ge.caseSize[0]
// const ay = v.pos.y * this.ge.caseSize[1]
// state.mouseHovering =
// this.ge.cursor.x >= ax && this.ge.cursor.x < (ax + width) &&
// this.ge.cursor.y >= ay && this.ge.cursor.y < (ay + height)
// state.mouseClicking = state.mouseHovering && this.ge.cursor.isDown
// state.mouseClicked = state.mouseClicking && !this.ge.cursor.wasDown
// }
if (v.renderer) {
if (debug) {
console.log('Rendering Component', v)
}
if (v.update) {
v.update(state as ComponentState)
// console.log('is rendering new element')
await v.renderer.render(this.ge, this.ge.ctx)
}
if (v.update) {
if (debug) {
console.log('Updating Component', v)
}
})
v.update(state as ComponentState)
}
if (v.childs) {
if (debug) {
console.log('Processing childs', v)
}
for (const child of v.childs) {
await this.updateComponent(child)
}
}
}
}

View File

@@ -1,12 +1,17 @@
import Asset from './Asset'
export interface TilesetDeclaration {
export type TilesetDeclaration = {
// id: string
// padding?: number
fileSize: {width: number, height: number}
tileSize: number | {width: number, height: number}
spacing?: number
}
} | Array<{
x: number
y: number
width: number
height: number
}>
export default class Tileset {
@@ -15,26 +20,37 @@ export default class Tileset {
private declaration: TilesetDeclaration
) {}
public getPosFromId(id: number): {x: number, y: number} {
const cols = Math.trunc(this.declaration.fileSize.width / this.width())
const x = id % cols
const y = Math.trunc(id / cols)
return {x, y}
}
// public getPosFromId(id: number): {x: number, y: number} {
// return {x, y}
// }
public getSourceData(id: number): {sx: number ,sy: number} {
const {x, y} = this.getPosFromId(id)
const sx = x * this.width() + x * (this.declaration.spacing ?? 0)
const sy = y * this.height() + y * (this.declaration.spacing ?? 0)
if (Array.isArray(this.declaration)) {
const item = this.declaration[id]
return {sx: item.x, sy: item.y}
}
// const {x, y} = this.getPosFromId(id)
const cols = Math.trunc(this.declaration.fileSize.width / this.width(id))
const x = id % cols
const y = Math.trunc(id / cols)
const sx = x * this.width(id) + x * (this.declaration.spacing ?? 0)
const sy = y * this.height(id) + y * (this.declaration.spacing ?? 0)
return {sx, sy}
}
public width() {
public width(id: number) {
if (Array.isArray(this.declaration)) {
return this.declaration[id].width
}
const item = this.declaration.tileSize
return typeof item === 'number' ? item : item.width
}
public height() {
public height(id: number) {
if (Array.isArray(this.declaration)) {
return this.declaration[id].height
}
const item = this.declaration.tileSize
return typeof item === 'number' ? item : item.height
}

View File

@@ -1,3 +1,4 @@
import Vector2D from './2D/Vector2D'
import Scene from './Scene'
/**
@@ -7,42 +8,43 @@ import Scene from './Scene'
* Collision
*/
export default class GameEngine {
private static ge: GameEngine
public ctx: CanvasRenderingContext2D
public canvas: HTMLCanvasElement
public caseSize: [number, number] = [1, 1]
public caseSize: Vector2D = new Vector2D(1, 1)
public cursor: {
x: number
y: number
position: Vector2D
isDown: boolean
wasDown: boolean
} = {
x: 0,
y: 0,
position: new Vector2D(0, 0),
isDown: false,
wasDown: false
}
private currentScene?: Scene
public currentScene!: Scene
private isRunning = false
public constructor(
private id: string,
private options?: {
public options?: {
caseCount?: number | [number, number]
background?: string
debugColliders?: boolean
}
) {
GameEngine.ge = this
const canvas = document.querySelector<HTMLCanvasElement>(id)
if (!canvas) {
throw new Error('Error, canvas not found!')
}
this.canvas = canvas
if (this.options?.caseCount) {
this.caseSize = [
this.caseSize = new Vector2D(
// @ts-expect-error idc
this.canvas.width / ((typeof this.options.caseCount) !== 'number' ? this.options.caseCount[0] : this.options.caseCount ),
// @ts-expect-error idc2 lol
this.canvas.height / ((typeof this.options.caseCount) !== 'number' ? this.options.caseCount[1] : this.options.caseCount)
]
)
}
const ctx = canvas.getContext('2d')
@@ -53,6 +55,10 @@ export default class GameEngine {
this.ctx = ctx
}
public static getGameEngine(): GameEngine {
return this.ge
}
public start() {
if (this.isRunning) {
console.warn('Game is already running')
@@ -63,8 +69,10 @@ export default class GameEngine {
this.update()
})
document.addEventListener('mousemove', (ev) => {
this.cursor.x = ev.clientX
this.cursor.y = ev.clientY
this.cursor.position = new Vector2D(
ev.clientX / this.caseSize.x - this.currentScene.camera.topLeft.x,
ev.clientY / this.caseSize.y - this.currentScene.camera.topLeft.y
)
if (this.cursor.isDown) {
this.cursor.wasDown = true
}
@@ -83,11 +91,11 @@ export default class GameEngine {
}
public setScene(scene: Scene | string) {
console.log('Setting scene', typeof scene === 'string' ? scene : scene.id)
this.currentScene = typeof scene === 'string' ? Scene.scenes[scene] : scene
this.currentScene.setGameEngine(this)
}
private update() {
if (!this.isRunning) {
return
@@ -103,3 +111,8 @@ export default class GameEngine {
}, 0)
}
}
export interface GameState<UserState = any> {
gameEngine: GameEngine
userState: UserState
}

View File

@@ -1,3 +1,4 @@
import Vector2D from 'GameEngine/2D/Vector2D'
import Asset from 'GameEngine/Asset'
import Component2D from 'GameEngine/Component2D'
import TileRenderer from 'GameEngine/Renderer/TileRenderer'
@@ -11,29 +12,33 @@ export class Explosion extends Component2D {
height: .9
}
// public origin = new Vector2D(-.5, -.5)
private explosionTileset = new Tileset(Asset.init('/assets/tictactoe/explosion.png'), {
fileSize: {width: 480, height: 362},
tileSize: 91,
spacing: 1,
fileSize: {width: 192, height: 32},
tileSize: 32
})
private animationNumber = -1
private n = 0
public update() {
if (this.animationNumber !== -1 && this.n++ >= 10) {
this.renderer = new TileRenderer(this, this.explosionTileset, this.animationNumber++)
if (this.animationNumber !== -1 && this.n++ >= 12) {
this.renderer = new TileRenderer(this, {
id: this.animationNumber++,
tileset: this.explosionTileset
})
this.n = 0
if (this.animationNumber >= 10) {
if (this.animationNumber > 5) {
this.animationNumber = -1
this.renderer = undefined
}
}
}
public run(pos: Component2D['pos']) {
new SoundManager('/assets/tictactoe/victory.wav').play()
this.pos = pos
public run(pos: Vector2D) {
new SoundManager('/assets/tictactoe/explosion.wav').play()
this.position = pos
this.animationNumber = 0
}
}

View File

@@ -1,5 +1,11 @@
import GameEngine from 'GameEngine'
import BoxCollider2D from 'GameEngine/2D/Collision/BoxCollider2D'
import ColliderDebugger from 'GameEngine/2D/Debug/ColliderDebugger'
import PointDebugger from 'GameEngine/2D/Debug/PointDebugger'
import Vector2D from 'GameEngine/2D/Vector2D'
import Asset from 'GameEngine/Asset'
import Component2D, { ComponentState } from 'GameEngine/Component2D'
import RectRenderer from 'GameEngine/Renderer/RectRenderer'
import TileRenderer from 'GameEngine/Renderer/TileRenderer'
import SoundManager from 'GameEngine/SoundManager'
import Tileset from 'GameEngine/Tileset'
@@ -10,28 +16,38 @@ export default class Item extends Component2D {
public static explosion = new Explosion()
public size = {
width: .9,
height: .9
}
public collider: BoxCollider2D = new BoxCollider2D(this, 'click')
private x: number
private y: number
private tileset = new Tileset(Asset.init('/assets/pokemon-shuffle/icons.png'), {
fileSize: {width: 3750, height: 3266},
tileSize: 121
private tileset = new Tileset(Asset.init('/assets/tictactoe/swsh.png'), {
fileSize: {width: 64, height: 32},
tileSize: 32
})
public constructor(index: number) {
super()
this.x = Math.trunc(index % 3)
this.y = Math.trunc(index / 3)
this.pos = {
x: this.x + this.x * .05,
y: this.y + this.y * .05
}
console.log(this.pos, index)
this.position = new Vector2D(
this.x,
this.y
)
this.scale = new Vector2D(
.9, .9
)
// this.renderer = new RectRenderer(this, {material: 'green'})
this.renderer = new TileRenderer(this, {tileset: this.tileset, id: -1})
// console.log(this.tileset.getSourceData(0), this.tileset.width(0), this.tileset.height(0))
// console.log(this.tileset.getSourceData(1))
this.childs = [
new ColliderDebugger(this, this.collider),
new PointDebugger(this.collider.pos()[0]),
new PointDebugger(this.collider.pos()[1])
]
// console.log(index)
}
public init() {
@@ -39,18 +55,23 @@ export default class Item extends Component2D {
}
public update(state: ComponentState) {
if (!globalState.isPlaying) {
return
}
// console.log(state)
const value: '' | 'X' | 'O' = globalState.gameState[this.x][this.y] as '' | 'X' | 'O'
if (state.mouseClicked && value === '') {
if (state.isColliding === 'click' && value === '') {
// console.log('hovering')
this.onClick()
}
if (value === 'X') {
this.renderer = new TileRenderer(this, this.tileset, 20)
(this.renderer as TileRenderer).id = 1
// this.renderer = new ImageRenderer(this, Asset.init('/assets/tictactoe/X.png'))
} else if(value === 'O') {
this.renderer = new TileRenderer(this, this.tileset, 54)
(this.renderer as TileRenderer).id = 0
} else {
(this.renderer as TileRenderer).id = -1
}
}
@@ -60,13 +81,15 @@ export default class Item extends Component2D {
globalState.gameState[this.x][this.y] = globalState.playerTurn
console.log(this.checkVictory())
if (this.checkVictory()) {
Item.explosion.run(this.pos)
Item.explosion.run(this.position)
globalState.gameState = [
['', '', ''],
['', '', ''],
['', '', '']
]
console.log(globalState)
GameEngine.getGameEngine().setScene('Menu')
return
}
globalState.playerTurn = globalState.playerTurn === 'X' ? 'O' : 'X'
}

View File

@@ -1,20 +1,31 @@
import Vector2D from 'GameEngine/2D/Vector2D'
import Component2D from 'GameEngine/Component2D'
import ColorRenderer from 'GameEngine/Renderer/ColorRenderer'
import RectRenderer from 'GameEngine/Renderer/RectRenderer'
export default class Line extends Component2D {
// public debug = true
public constructor(direction: number, index: number) {
super()
this.renderer = new ColorRenderer(this, 'orange')
this.renderer = new RectRenderer(this, {material: 'orange'})
this.pos = {
x: direction ? index ? 1.95 : .9 : 0,
y: direction ? 0 : index ? .9 : 1.95
}
this.size = {
width: direction ? .15 : 3,
height: direction ? 3 : .15
}
this.position = new Vector2D(
direction ? index ? 1.5 : 0.5 : 1,
direction ? 1 : index ? 0.5 : 1.5
)
this.scale = new Vector2D(
direction ? .1 : 3,
direction ? 3 : .1
)
// this.origin = new Vector2D(
// -this.scale.x / 2,
// 0
// )
// this.childs = [new ComponentDebug(this)]
}
}

View File

@@ -0,0 +1,23 @@
import GameEngine from 'GameEngine'
import BoxCollider2D from 'GameEngine/2D/Collision/BoxCollider2D'
import ColliderDebugger from 'GameEngine/2D/Debug/ColliderDebugger'
import Vector2D from 'GameEngine/2D/Vector2D'
import Component2D, { ComponentState } from 'GameEngine/Component2D'
import RectRenderer from 'GameEngine/Renderer/RectRenderer'
import { globalState } from '..'
export default class Start extends Component2D {
public renderer: RectRenderer = new RectRenderer(this, {material: 'yellow'})
public position: Vector2D = new Vector2D(1, 1)
public scale: Vector2D = new Vector2D(2, 1)
public collider: BoxCollider2D = new BoxCollider2D(this, 'click')
public childs: Array<Component2D> = [new ColliderDebugger(this, this.collider)]
public update(state: ComponentState) {
if (state.isColliding === 'click') {
console.log('Start Game !')
GameEngine.getGameEngine().setScene('TicTacToe')
globalState.isPlaying = true
}
}
}

View File

@@ -5,11 +5,13 @@ export const globalState: {
[string, string, string],
[string, string, string],
]
isPlaying: boolean
} = {
playerTurn: 'X',
gameState: [
['', '', ''],
['', '', ''],
['', '', '']
]
],
isPlaying: false
}

View File

@@ -7,6 +7,7 @@ export const getServerSideProps: GetServerSideProps = async ({res}) => {
const sitemap = new Sitemap('https://games.avior.me', {response: res})
sitemap.addEntry('/')
sitemap.addEntry('/pokemon-shuffle')
sitemap.addEntry('/tictactoe')
sitemap.build()
return {
notFound: true

View File

@@ -5,31 +5,44 @@ import GameEngine from 'GameEngine'
import Scene from 'GameEngine/Scene'
import Item from 'games/tictactoe/Item'
import Line from 'games/tictactoe/Line'
import Start from 'games/tictactoe/Menu/Start'
export default class Snake extends React.PureComponent {
public async componentDidMount() {
const ge = new GameEngine('#test', {
caseCount: 3,
background: 'blue'
background: 'blue',
debugColliders: true
})
const menuScene = new Scene('Menu')
menuScene.addComponent(
new Start()
)
const scene = new Scene('TicTacToe')
scene.addComponent(
...Array.from(new Array(2)).map((_, index) => new Line(0, index)),
...Array.from(new Array(2)).map((_, index) => new Line(1, index)),
...Array.from(new Array(9)).map((_, index) => new Item(index)),
Item.explosion
// new TilingDebugger()
)
ge.start()
ge.setScene(scene)
ge.setScene(menuScene)
}
public render = () => (
<>
<canvas id="test" width="300" height="300"></canvas>
<Text>
<span id="debug"></span>
</Text>
<Text>Explositon animation from <Link href="https://opengameart.org/content/explosion-animations">https://opengameart.org/content/explosion-animations</Link></Text>
<Text>Bienvenue sur le TicTacToe le plus Overengineered du monde xd<br /> Avec un moteur de jeux complètement fait maison et bien plus encore en préparation ! (vieille version en 75 lignes, nouvelle en plus de 200 lol)</Text>
<Text>
Bienvenue sur le TicTacToe le plus Overengineered du monde xd<br />
Avec un moteur de jeux complètement fait maison et bien plus encore en préparation ! (vieille version en 75 lignes, nouvelle en plus de 200 lol)
</Text>
<Text>Version faites il y a 4 ans encore disponible sur Github lol <Link href="https://github.com/Aviortheking/TicTacToe">https://github.com/Aviortheking/TicTacToe</Link></Text>
</>
)