Skip to content

Commit

Permalink
Improving game natives for performance
Browse files Browse the repository at this point in the history
  • Loading branch information
PalumboN committed Dec 27, 2024
1 parent 9ca1223 commit 1cee6c3
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 44 deletions.
95 changes: 53 additions & 42 deletions src/wre/game.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,45 @@
import { GAME_MODULE } from '../constants'
import { assertIsNumber, assertIsNotNull, Execution, Natives, RuntimeObject, RuntimeValue } from '../interpreter/runtimeModel'
import { assertIsNotNull, assertIsNumber, Execution, NativeFunction, Natives, RuntimeObject, RuntimeValue } from '../interpreter/runtimeModel'
const { round } = Math



Check warning on line 6 in src/wre/game.ts

View workflow job for this annotation

GitHub Actions / build

More than 2 blank lines not allowed
/**
* Avoid to invoke getters method from properties by accessing directly to the variable
*/
const getter = (message: string): NativeFunction => function* (obj: RuntimeObject): Execution<RuntimeValue> {
const method = obj.module.lookupMethod(message, 0)!
return method.isSynthetic ? obj.get(message)! : yield* this.invoke(method, obj)
}

const getPosition = getter('position')
const getX = getter('x')
const getY = getter('y')

const getObjectsIn: NativeFunction = function* (position: RuntimeObject, ...visuals: RuntimeObject[]): Execution<RuntimeValue> {
const result: RuntimeObject[] = []

const x = (yield* getX.call(this, position))?.innerNumber
const y = (yield* getY.call(this, position))?.innerNumber

if (x == undefined || y == undefined) throw new RangeError('Position without coordinates')

const roundedX = round(x)
const roundedY = round(y)
for (const visual of visuals) {
const otherPosition = (yield* getPosition.call(this, visual))!
const otherX = (yield* getX.call(this, otherPosition))?.innerNumber
const otherY = (yield* getY.call(this, otherPosition))?.innerNumber

if (otherX == undefined || otherY == undefined) continue // Do NOT throw exception

if (roundedX == round(otherX) && roundedY == round(otherY))
result.push(visual)
}

return yield* this.list(...result)
}

const game: Natives = {
game: {
*addVisual(self: RuntimeObject, positionable: RuntimeObject): Execution<void> {
Expand Down Expand Up @@ -30,33 +68,7 @@ const game: Natives = {

*getObjectsIn(self: RuntimeObject, position: RuntimeObject): Execution<RuntimeValue> {
const visuals = self.get('visuals')!
const result: RuntimeObject[] = []
const x = position.get('x')?.innerNumber
const y = position.get('y')?.innerNumber


if(x != undefined && y != undefined) {
const roundedX = round(x)
const roundedY = round(y)
for(const visual of visuals.innerCollection!) {

// Every visual understand position(), it is checked in addVisual(visual).
// Avoid to invoke method position() for optimisation reasons.
// -> If method isSynthetic then it is a getter, we can access to the field directly
const method = visual.module.lookupMethod('position', 0)!
const otherPosition = method.isSynthetic ? visual.get('position') :yield* this.invoke(method, visual)

const otherX = otherPosition?.get('x')?.innerNumber
const otherY = otherPosition?.get('y')?.innerNumber

if(otherX == undefined || otherY == undefined) continue

if(roundedX == round(otherX) && roundedY == round(otherY))
result.push(visual)
}
}

return yield* this.list(...result)
return (yield* getObjectsIn.call(this, position, ...visuals.innerCollection!))!
},

*say(self: RuntimeObject, visual: RuntimeObject, message: RuntimeObject): Execution<void> {
Expand All @@ -70,27 +82,26 @@ const game: Natives = {

*colliders(self: RuntimeObject, visual: RuntimeObject): Execution<RuntimeValue> {
assertIsNotNull(visual, 'colliders', 'visual')

const position = (yield* this.send('position', visual))!
const visualsAtPosition: RuntimeObject = (yield* this.send('getObjectsIn', self, position))!

yield* this.send('remove', visualsAtPosition, visual)

return visualsAtPosition

Check warning on line 85 in src/wre/game.ts

View workflow job for this annotation

GitHub Actions / build

Trailing spaces not allowed
const visuals = self.get('visuals')!
const otherVisuals = visuals.innerCollection!.filter(obj => obj != visual)
const position = (yield* getPosition.call(this, visual))!

Check warning on line 89 in src/wre/game.ts

View workflow job for this annotation

GitHub Actions / build

Trailing spaces not allowed
return (yield* getObjectsIn.call(this, position, ...otherVisuals))!
},

*title(self: RuntimeObject, title?: RuntimeObject): Execution<RuntimeValue> {
if(!title) return self.get('title')
if (!title) return self.get('title')
self.set('title', title)
},

*width(self: RuntimeObject, width?: RuntimeObject): Execution<RuntimeValue> {
if(!width) return self.get('width')
if (!width) return self.get('width')
self.set('width', width)
},

*height(self: RuntimeObject, height?: RuntimeObject): Execution<RuntimeValue> {
if(!height) return self.get('height')
if (!height) return self.get('height')
self.set('height', height)
},

Expand Down Expand Up @@ -135,9 +146,9 @@ const game: Natives = {

const game = this.object(GAME_MODULE)!
const sounds = game.get('sounds')
if(sounds) yield* this.send('remove', sounds, self)
if (sounds) yield* this.send('remove', sounds, self)

self.set('status', yield * this.reify('stopped'))
self.set('status', yield* this.reify('stopped'))
},

*pause(self: RuntimeObject): Execution<void> {
Expand All @@ -161,7 +172,7 @@ const game: Natives = {
},

*volume(self: RuntimeObject, newVolume?: RuntimeObject): Execution<RuntimeValue> {
if(!newVolume) return self.get('volume')
if (!newVolume) return self.get('volume')

const volume: RuntimeObject = newVolume
assertIsNumber(volume, 'volume', 'newVolume', false)
Expand All @@ -172,7 +183,7 @@ const game: Natives = {
},

*shouldLoop(self: RuntimeObject, looping?: RuntimeObject): Execution<RuntimeValue> {
if(!looping) return self.get('loop')
if (!looping) return self.get('loop')
self.set('loop', looping)
},

Expand Down
4 changes: 2 additions & 2 deletions test/benchmarks.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { should } from 'chai'
import { resolve } from 'path'
import { Environment, Execution, get, Natives, PROGRAM_FILE_EXTENSION, RuntimeObject } from '../src'
import { interpret, interprete, Interpreter } from '../src/interpreter/interpreter'
import { Environment, PROGRAM_FILE_EXTENSION } from '../src'
import { interpret, Interpreter } from '../src/interpreter/interpreter'
import natives from '../src/wre/wre.natives'
import { buildEnvironment } from './assertions'

Expand Down

0 comments on commit 1cee6c3

Please sign in to comment.