mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-04-06 17:39:40 +00:00
ecs: actions emit?
This commit is contained in:
parent
d2caee8cc3
commit
310ce87bcc
90
ecsroot/kernel.txt
Normal file
90
ecsroot/kernel.txt
Normal file
@ -0,0 +1,90 @@
|
||||
# Kernel
|
||||
# A Kernel draws a set of scanlines to the screen.
|
||||
|
||||
component Kernel
|
||||
lines: 0..255 "Height of region in scanlines"
|
||||
bgcolor: 0..255 "Background color"
|
||||
end
|
||||
|
||||
system SimpleKernel
|
||||
tempbytes 8
|
||||
on preframe do once [Kernel] ---
|
||||
lda #192 ; TODO: numlines
|
||||
sec
|
||||
sbc ypos_ypos_b0+ent
|
||||
sta {{$5}}+ofs
|
||||
|
||||
ldy hasbitmap_bitmap_b0+ent
|
||||
lda bitmap_bitmapdata_b0,y
|
||||
sec
|
||||
sbc {{$5}}+ofs
|
||||
sta {{$0}}+ofs
|
||||
lda bitmap_bitmapdata_b8,y
|
||||
sbc #0
|
||||
sta {{$1}}+ofs
|
||||
|
||||
ldy hascolormap_colormap_b0+ent
|
||||
lda colormap_colormapdata_b0,y
|
||||
sec
|
||||
sbc {{$5}}+ofs
|
||||
sta {{$2}}+ofs
|
||||
lda colormap_colormapdata_b8,y
|
||||
sbc #0
|
||||
sta {{$3}}+ofs
|
||||
|
||||
lda sprite_height_b0+ent
|
||||
sta {{$4}}+ofs
|
||||
lda ypos_ypos_b0+ent
|
||||
sta {{$5}}+ofs
|
||||
---
|
||||
on preframe do once [Sprite,HasBitmap,HasColormap,HasYpos] --
|
||||
{{@KernelSetup}} 0,0
|
||||
{{@KernelSetup}} 1,6
|
||||
--
|
||||
on kernel do once [Kernel]:
|
||||
lda %{<bgcolor}
|
||||
sta COLUBK
|
||||
ldy %{<lines}
|
||||
@LVScan:
|
||||
lda %{$4} ; height
|
||||
dcp %{$5}
|
||||
bcs @DoDraw1
|
||||
lda #0
|
||||
.byte $2C
|
||||
@DoDraw1:
|
||||
lda (%{$0}),y
|
||||
sta WSYNC
|
||||
sta GRP0
|
||||
lda (%{$2}),y
|
||||
sta COLUP0
|
||||
|
||||
lda %{$10} ; height
|
||||
dcp %{$11}
|
||||
bcs @DoDraw2
|
||||
lda #0
|
||||
.byte $2C
|
||||
@DoDraw2:
|
||||
lda (%{$6}),y
|
||||
sta GRP1
|
||||
lda (%{$8}),y
|
||||
sta COLUP1
|
||||
|
||||
dey ; decrement
|
||||
bne @LVScan ; repeat until 192 lines
|
||||
--
|
||||
end
|
||||
|
||||
scope Root
|
||||
|
||||
entity kernel [SimpleKernel]
|
||||
const lines = 100
|
||||
end
|
||||
|
||||
entity player1 [Sprite,HasBitmap,HasColormap,HasYpos]
|
||||
const plyrindex = 0
|
||||
init height = 8
|
||||
init xpos = 100
|
||||
init ypos = 100
|
||||
end
|
||||
|
||||
end scope
|
279
ecsroot/vcs/kernel.ecs
Normal file
279
ecsroot/vcs/kernel.ecs
Normal file
@ -0,0 +1,279 @@
|
||||
|
||||
component Kernel
|
||||
lines: 0..255
|
||||
bgcolor: 0..255
|
||||
end
|
||||
|
||||
component Bitmap
|
||||
bitmapdata: array of 0..255
|
||||
end
|
||||
|
||||
component HasBitmap
|
||||
bitmap: [Bitmap]
|
||||
end
|
||||
|
||||
component Colormap
|
||||
colormapdata: array of 0..255
|
||||
end
|
||||
|
||||
component HasColormap
|
||||
colormap: [Colormap]
|
||||
end
|
||||
|
||||
component Sprite
|
||||
height: 0..255
|
||||
plyrindex: 0..1
|
||||
end
|
||||
|
||||
component Player end
|
||||
|
||||
component PlayerFlags
|
||||
plyrflags: 0..63
|
||||
end
|
||||
|
||||
component HasXpos
|
||||
xpos: 0..255
|
||||
end
|
||||
|
||||
component HasYpos
|
||||
ypos: 0..255
|
||||
end
|
||||
|
||||
component HasXYVel
|
||||
xyvel: 0..255
|
||||
end
|
||||
|
||||
system FrameLoop
|
||||
on start do once [Kernel] emit (preframe, kernel, postframe)
|
||||
---
|
||||
{{@NextFrame}}:
|
||||
FRAME_START
|
||||
{{!preframe}}
|
||||
KERNEL_START
|
||||
{{!kernel}}
|
||||
KERNEL_END
|
||||
{{!postframe}}
|
||||
FRAME_END
|
||||
lsr SWCHB ; test Game Reset switch
|
||||
bcs {{@NoStart}}
|
||||
jmp Start
|
||||
{{@NoStart}}:
|
||||
jmp {{@NextFrame}}
|
||||
---
|
||||
end
|
||||
|
||||
system SimpleKernel
|
||||
locals 12
|
||||
on preframe do each [Sprite,HasBitmap,HasColormap,HasYpos]
|
||||
---
|
||||
lda #192 ; TODO: numlines
|
||||
sec
|
||||
sbc {{<ypos}}
|
||||
sta {{$11}}
|
||||
|
||||
ldy {{<bitmap}} ; deref
|
||||
lda Bitmap_bitmapdata_b0,y
|
||||
sec
|
||||
sbc {{$11}}
|
||||
sta {{$0}},x
|
||||
lda Bitmap_bitmapdata_b8,y
|
||||
sbc #0
|
||||
sta {{$2}},x
|
||||
|
||||
ldy {{<colormap}}
|
||||
lda Colormap_colormapdata_b0,y
|
||||
sec
|
||||
sbc {{$11}}
|
||||
sta {{$4}},x
|
||||
lda Colormap_colormapdata_b8,y
|
||||
sbc #0
|
||||
sta {{$6}},x
|
||||
|
||||
lda {{<height}}
|
||||
sta {{$8}},x
|
||||
lda {{<ypos}}
|
||||
sta {{$10}},x
|
||||
---
|
||||
on preframe do once [Sprite,HasBitmap,HasColormap,HasYpos]
|
||||
---
|
||||
; L0 L1 H0 H1 -> L0 H0 L1 H1
|
||||
lda {{$1}}
|
||||
ldy {{$2}}
|
||||
sty {{$1}}
|
||||
sta {{$2}}
|
||||
lda {{$5}}
|
||||
ldy {{$6}}
|
||||
sty {{$5}}
|
||||
sta {{$6}}
|
||||
---
|
||||
on kernel do once [Kernel]
|
||||
---
|
||||
lda {{<bgcolor}}
|
||||
sta COLUBK
|
||||
ldy {{<lines}}
|
||||
@LVScan:
|
||||
lda {{$8}} ; height
|
||||
dcp {{$10}} ; ypos
|
||||
bcs @DoDraw1
|
||||
lda #0
|
||||
.byte $2C
|
||||
@DoDraw1:
|
||||
lda ({{$0}}),y
|
||||
sta WSYNC
|
||||
sta GRP0
|
||||
lda ({{$4}}),y
|
||||
sta COLUP0
|
||||
|
||||
lda {{$9}} ; height
|
||||
dcp {{$11}} ; ypos
|
||||
bcs @DoDraw2
|
||||
lda #0
|
||||
.byte $2C
|
||||
@DoDraw2:
|
||||
lda ({{$2}}),y
|
||||
sta GRP1
|
||||
lda ({{$6}}),y
|
||||
sta COLUP1
|
||||
|
||||
dey ; decrement
|
||||
bne @LVScan ; repeat until 192 lines
|
||||
---
|
||||
end
|
||||
|
||||
system SetXPos
|
||||
on preframe do each [Sprite,HasXpos] emit (SetHorizPos)
|
||||
---
|
||||
lda {{<xpos}}
|
||||
ldy {{<plyrindex}}
|
||||
sta HMCLR
|
||||
jsr {{^SetHorizPos}}
|
||||
---
|
||||
end
|
||||
|
||||
system SetHorizPos
|
||||
on SetHorizPos do once [HasXpos]
|
||||
---
|
||||
; SetHorizPos routine
|
||||
; A = X coordinate
|
||||
; Y = player number (0 or 1)
|
||||
SetHorizPos:
|
||||
sta WSYNC ; start a new line
|
||||
sec ; set carry flag
|
||||
nop
|
||||
@DivideLoop:
|
||||
sbc #15 ; subtract 15
|
||||
bcs @DivideLoop ; branch until negative
|
||||
eor #7 ; calculate fine offset
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
asl
|
||||
sta RESP0,y ; fix coarse position
|
||||
sta HMP0,y ; set fine offset
|
||||
sta WSYNC
|
||||
sta HMOVE
|
||||
rts ; return to caller
|
||||
---
|
||||
end
|
||||
|
||||
system JoyRead
|
||||
locals 1
|
||||
on postframe do once [Player]
|
||||
---
|
||||
lda SWCHA
|
||||
sta {{$0}}
|
||||
---
|
||||
on postframe do each [Player] emit (joyup, joydown, joyleft, joyright, joybutton)
|
||||
---
|
||||
asl {{$0}}
|
||||
bcs {{@SkipMoveRight}}
|
||||
{{!joyright}}
|
||||
{{@SkipMoveRight}}:
|
||||
asl {{$0}}
|
||||
bcs {{@SkipMoveLeft}}
|
||||
{{!joyleft}}
|
||||
{{@SkipMoveLeft}}:
|
||||
asl {{$0}}
|
||||
bcs {{@SkipMoveDown}}
|
||||
{{!joydown}}
|
||||
{{@SkipMoveDown}}:
|
||||
asl {{$0}}
|
||||
bcs {{@SkipMoveUp}}
|
||||
{{!joyup}}
|
||||
{{@SkipMoveUp}}:
|
||||
---
|
||||
end
|
||||
|
||||
system MoveJoyX
|
||||
on joyleft do source [HasXpos]
|
||||
---
|
||||
lda {{<xpos}}
|
||||
sec
|
||||
sbc #1
|
||||
bcc {{@nomove}}
|
||||
sta {{<xpos}}
|
||||
{{@nomove}}:
|
||||
---
|
||||
on joyright do source [HasXpos]
|
||||
---
|
||||
lda {{<xpos}}
|
||||
clc
|
||||
adc #1
|
||||
cmp #150
|
||||
bcs {{@nomove}}
|
||||
sta {{<xpos}}
|
||||
{{@nomove}}:
|
||||
---
|
||||
end
|
||||
|
||||
system MoveJoyY
|
||||
on joyup do source [HasYpos]
|
||||
---
|
||||
lda {{<ypos}}
|
||||
sec
|
||||
sbc #1
|
||||
bcc {{@nomove}}
|
||||
sta {{<ypos}}
|
||||
{{@nomove}}:
|
||||
---
|
||||
on joydown do source [HasYpos]
|
||||
---
|
||||
lda {{<ypos}}
|
||||
clc
|
||||
adc #1
|
||||
cmp #150
|
||||
bcs {{@nomove}}
|
||||
sta {{<ypos}}
|
||||
{{@nomove}}:
|
||||
---
|
||||
end
|
||||
|
||||
scope Main
|
||||
entity Kernel [Kernel]
|
||||
const lines = 192
|
||||
const bgcolor = 0xa2
|
||||
end
|
||||
entity Bitmap1 [Bitmap]
|
||||
const bitmapdata = [1, 1, 3, 7, 15, 31, 63, 127]
|
||||
end
|
||||
entity Bitmap2 [Bitmap]
|
||||
const bitmapdata = [$18,$3e,$ff,$ff,$ff,$ff,$3e,$18]
|
||||
end
|
||||
entity Colormap1 [Colormap]
|
||||
const colormapdata = [6, 3, 6, 9, 12, 14, 31, 63]
|
||||
end
|
||||
entity Player0 [Sprite,HasBitmap,HasColormap,HasXpos,HasYpos,Player]
|
||||
const plyrindex = 0
|
||||
init height = 8
|
||||
init xpos = 50
|
||||
init ypos = 50
|
||||
end
|
||||
entity Player1 [Sprite,HasBitmap,HasColormap,HasXpos,HasYpos,Player]
|
||||
const plyrindex = 1
|
||||
init height = 8
|
||||
init xpos = 100
|
||||
init ypos = 60
|
||||
init bitmap = 1
|
||||
end
|
||||
end
|
||||
|
@ -18,11 +18,13 @@ export class ECSCompiler extends Tokenizer {
|
||||
super();
|
||||
//this.includeEOL = true;
|
||||
this.setTokenRules([
|
||||
{ type: TokenType.Ident, regex: /[$A-Za-z_][A-Za-z0-9_-]*/ },
|
||||
{ type: TokenType.Ident, regex: /[A-Za-z_][A-Za-z0-9_]*/ },
|
||||
{ type: TokenType.CodeFragment, regex: /---/ },
|
||||
{ type: ECSTokenType.Ellipsis, regex: /\.\./ },
|
||||
{ type: ECSTokenType.Operator, regex: /[=,:(){}\[\]]/ },
|
||||
{ type: ECSTokenType.Operator, regex: /[#=,:(){}\[\]]/ },
|
||||
{ type: ECSTokenType.QuotedString, regex: /".*?"/ },
|
||||
{ type: ECSTokenType.Integer, regex: /[-]?0x[A-Fa-f0-9]+/ },
|
||||
{ type: ECSTokenType.Integer, regex: /[-]?\$[A-Fa-f0-9]+/ },
|
||||
{ type: ECSTokenType.Integer, regex: /[-]?\d+/ },
|
||||
{ type: TokenType.Ignore, regex: /\s+/ },
|
||||
]);
|
||||
@ -91,14 +93,33 @@ export class ECSCompiler extends Tokenizer {
|
||||
}
|
||||
|
||||
parseDataValue() : DataValue {
|
||||
if (this.peekToken().type == 'integer') {
|
||||
let tok = this.peekToken();
|
||||
if (tok.type == 'integer') {
|
||||
return this.expectInteger();
|
||||
}
|
||||
if (tok.str == '[') {
|
||||
// TODO: 16-bit?
|
||||
return new Uint8Array(this.parseDataArray());
|
||||
}
|
||||
if (tok.str == '#') {
|
||||
let e = this.parseEntityRef();
|
||||
// TODO: entity ref types by query?
|
||||
return e.id;
|
||||
}
|
||||
this.compileError(`Unknown data value`); // TODO
|
||||
}
|
||||
|
||||
parseDataArray() {
|
||||
this.expectToken('[');
|
||||
let arr = this.parseList(this.expectInteger, ',');
|
||||
this.expectToken(']');
|
||||
return arr;
|
||||
}
|
||||
|
||||
expectInteger(): number {
|
||||
let i = parseInt(this.consumeToken().str);
|
||||
let s = this.consumeToken().str;
|
||||
if (s.startsWith('$')) s = '0x' + s.substring(1);
|
||||
let i = parseInt(s);
|
||||
if (isNaN(i)) this.compileError('There should be an integer here.');
|
||||
return i;
|
||||
}
|
||||
@ -123,12 +144,19 @@ export class ECSCompiler extends Tokenizer {
|
||||
parseAction(): Action {
|
||||
let event = this.expectIdent().str;
|
||||
this.expectToken('do');
|
||||
let select = this.expectTokens(['once', 'each']).str as SelectType; // TODO: type check?
|
||||
let select = this.expectTokens(['once', 'each', 'source']).str as SelectType; // TODO: type check?
|
||||
let query = this.parseQuery();
|
||||
let emits;
|
||||
if (this.peekToken().str == 'emit') {
|
||||
this.consumeToken();
|
||||
this.expectToken('(');
|
||||
emits = this.parseEventList();
|
||||
this.expectToken(')');
|
||||
}
|
||||
let text = this.parseCode();
|
||||
return { text, event, query, select };
|
||||
}
|
||||
|
||||
|
||||
parseQuery() {
|
||||
let q: Query = { include: [] };
|
||||
this.expectToken('[');
|
||||
@ -142,6 +170,10 @@ export class ECSCompiler extends Tokenizer {
|
||||
return this.expectIdent().str;
|
||||
}
|
||||
|
||||
parseEventList() {
|
||||
return this.parseList(this.parseEvent, ",");
|
||||
}
|
||||
|
||||
parseCode(): string {
|
||||
return this.expectTokenTypes([TokenType.CodeFragment]).str;
|
||||
}
|
||||
@ -173,14 +205,15 @@ export class ECSCompiler extends Tokenizer {
|
||||
let cmd;
|
||||
while ((cmd = this.consumeToken().str) != 'end') {
|
||||
// TODO: check data types
|
||||
if (cmd == 'const') {
|
||||
if (cmd == 'const' || cmd == 'init') {
|
||||
let name = this.expectIdent().str;
|
||||
this.expectToken('=');
|
||||
e.consts[name] = this.parseDataValue();
|
||||
} else if (cmd == 'init') {
|
||||
let name = this.expectIdent().str;
|
||||
this.expectToken('=');
|
||||
e.inits[name] = this.parseDataValue();
|
||||
let comps = this.em.componentsWithFieldName([{etype: e.etype, cmatch:e.etype.components}], name);
|
||||
if (comps.length == 0) this.compileError(`I couldn't find a field named "${name}" for this entity.`)
|
||||
if (comps.length > 1) this.compileError(`I found more than one field named "${name}" for this entity.`)
|
||||
let value = this.parseDataValue();
|
||||
if (cmd == 'const') this.currentScope.setConstValue(e, comps[0], name, value);
|
||||
if (cmd == 'init') this.currentScope.setInitValue(e, comps[0], name, value);
|
||||
} else {
|
||||
this.compileError(`Unexpected scope keyword: ${cmd}`);
|
||||
}
|
||||
@ -202,6 +235,14 @@ export class ECSCompiler extends Tokenizer {
|
||||
return cref;
|
||||
}
|
||||
|
||||
parseEntityRef() : Entity {
|
||||
this.expectToken('#');
|
||||
let name = this.expectIdent().str;
|
||||
let eref = this.currentScope.entities.find(e => e.name == name);
|
||||
if (!eref) this.compileError(`I couldn't find an entity named "${name}" in this scope.`)
|
||||
return eref;
|
||||
}
|
||||
|
||||
exportToFile(src: SourceFileExport) {
|
||||
for (let scope of Object.values(this.em.scopes)) {
|
||||
scope.analyzeEntities();
|
||||
|
@ -29,8 +29,6 @@
|
||||
// - converting assets to native formats?
|
||||
// - removing unused data
|
||||
|
||||
import { Token } from "../tokenizer";
|
||||
|
||||
function mksymbol(c: ComponentType, fieldName: string) {
|
||||
return c.name + '_' + fieldName;
|
||||
}
|
||||
@ -73,7 +71,6 @@ export interface System {
|
||||
name: string;
|
||||
actions: Action[];
|
||||
tempbytes?: number;
|
||||
emits?: string[];
|
||||
}
|
||||
|
||||
export interface Action {
|
||||
@ -81,6 +78,7 @@ export interface Action {
|
||||
event: string;
|
||||
query: Query;
|
||||
select: SelectType
|
||||
emits?: string[];
|
||||
}
|
||||
|
||||
export type SelectType = 'once' | 'each' | 'source';
|
||||
@ -132,6 +130,11 @@ interface ArchetypeMatch {
|
||||
cmatch: ComponentType[];
|
||||
}
|
||||
|
||||
interface ComponentFieldPair {
|
||||
c: ComponentType;
|
||||
f: DataField;
|
||||
}
|
||||
|
||||
export class Dialect_CA65 {
|
||||
readonly ASM_ITERATE_EACH = `
|
||||
ldx #0
|
||||
@ -297,6 +300,7 @@ export class EntityScope {
|
||||
code = new Segment();
|
||||
componentsInScope = new Set();
|
||||
tempOffset = 0;
|
||||
tempSize = 0;
|
||||
maxTempBytes = 0;
|
||||
subroutines = new Set<string>();
|
||||
|
||||
@ -415,7 +419,8 @@ export class EntityScope {
|
||||
if (offset !== undefined && typeof initvalue === 'number') {
|
||||
initbytes[offset] = initvalue; // TODO: > 8 bits?
|
||||
} else {
|
||||
throw new Error(`cannot access ${scfname}`);
|
||||
// TODO: init arrays?
|
||||
throw new Error(`cannot initialize ${scfname}: ${offset} ${initvalue}`); // TODO??
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -431,11 +436,11 @@ export class EntityScope {
|
||||
return code;
|
||||
}
|
||||
setConstValue(e: Entity, component: ComponentType, fieldName: string, value: DataValue) {
|
||||
// TODO: check to make sure component exists
|
||||
let c = this.em.singleComponentWithFieldName([{etype: e.etype, cmatch:[component]}], fieldName, "setConstValue");
|
||||
e.consts[mksymbol(component, fieldName)] = value;
|
||||
}
|
||||
setInitValue(e: Entity, component: ComponentType, fieldName: string, value: DataValue) {
|
||||
// TODO: check to make sure component exists
|
||||
let c = this.em.singleComponentWithFieldName([{etype: e.etype, cmatch:[component]}], fieldName, "setConstValue");
|
||||
e.inits[mkscopesymbol(this, component, fieldName)] = value;
|
||||
}
|
||||
generateCodeForEvent(event: string): string {
|
||||
@ -450,21 +455,21 @@ export class EntityScope {
|
||||
let emitcode: { [event: string]: string } = {};
|
||||
for (let sys of systems) {
|
||||
// TODO: does this work if multiple actions?
|
||||
// TODO: should 'emits' be on action?
|
||||
if (sys.tempbytes) this.allocateTempBytes(sys.tempbytes);
|
||||
if (sys.emits) {
|
||||
for (let emit of sys.emits) {
|
||||
if (emitcode[emit]) {
|
||||
console.log(`already emitted for ${sys.name}:${event}`);
|
||||
}
|
||||
//console.log('>', emit);
|
||||
// TODO: cycles
|
||||
emitcode[emit] = this.generateCodeForEvent(emit);
|
||||
//console.log('<', emit, emitcode[emit].length);
|
||||
}
|
||||
}
|
||||
if (sys.tempbytes) this.allocateTempBytes(-sys.tempbytes);
|
||||
for (let action of sys.actions) {
|
||||
if (action.event == event) {
|
||||
if (action.emits) {
|
||||
for (let emit of action.emits) {
|
||||
if (emitcode[emit]) {
|
||||
console.log(`already emitted for ${sys.name}:${event}`);
|
||||
}
|
||||
//console.log('>', emit);
|
||||
// TODO: cycles
|
||||
emitcode[emit] = this.generateCodeForEvent(emit);
|
||||
//console.log('<', emit, emitcode[emit].length);
|
||||
}
|
||||
}
|
||||
let code = this.replaceCode(action.text, sys, action);
|
||||
s += this.dialect.comment(`<action ${sys.name}:${event}>`);
|
||||
s += code;
|
||||
@ -472,12 +477,15 @@ export class EntityScope {
|
||||
// TODO: check that this happens once?
|
||||
}
|
||||
}
|
||||
if (sys.tempbytes) this.allocateTempBytes(-sys.tempbytes);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
allocateTempBytes(n: number) {
|
||||
this.tempOffset += n;
|
||||
this.maxTempBytes = Math.max(this.tempOffset, this.maxTempBytes);
|
||||
if (n > 0) this.tempOffset = this.tempSize;
|
||||
this.tempSize += n;
|
||||
this.maxTempBytes = Math.max(this.tempSize, this.maxTempBytes);
|
||||
if (n < 0) this.tempOffset = this.tempSize;
|
||||
}
|
||||
replaceCode(code: string, sys: System, action: Action): string {
|
||||
const re = /\{\{(.+?)\}\}/g;
|
||||
@ -512,9 +520,7 @@ export class EntityScope {
|
||||
case '^': // reference
|
||||
return this.includeSubroutine(rest);
|
||||
default:
|
||||
//throw new Error(`unrecognized command ${cmd} in ${entire}`);
|
||||
console.log(`unrecognized command ${cmd} in ${entire}`);
|
||||
return entire;
|
||||
throw new Error(`unrecognized command ${cmd} in ${entire}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -536,10 +542,7 @@ export class EntityScope {
|
||||
atypes: ArchetypeMatch[], entities: Entity[],
|
||||
fieldName: string, bitofs: number): string {
|
||||
// find archetypes
|
||||
let component = this.em.componentWithFieldName(atypes, fieldName);
|
||||
if (!component) {
|
||||
throw new Error(`cannot find component with field "${fieldName}" in ${sys.name}:${action.event}`);
|
||||
}
|
||||
let component = this.em.singleComponentWithFieldName(atypes, fieldName, `${sys.name}:${action.event}`);
|
||||
// see if all entities have the same constant value
|
||||
let constValues = new Set<DataValue>();
|
||||
for (let e of entities) {
|
||||
@ -583,7 +586,7 @@ export class EntityScope {
|
||||
return result;
|
||||
}
|
||||
getSystems(events: string[]) {
|
||||
let result = [];
|
||||
let result : System[] = [];
|
||||
for (let sys of Object.values(this.em.systems)) {
|
||||
if (this.systemListensTo(sys, events)) {
|
||||
result.push(sys);
|
||||
@ -684,20 +687,32 @@ export class EntityManager {
|
||||
});
|
||||
return result;
|
||||
}
|
||||
componentWithFieldName(atypes: ArchetypeMatch[], fieldName: string) {
|
||||
componentsWithFieldName(atypes: ArchetypeMatch[], fieldName: string) {
|
||||
// TODO???
|
||||
let comps = new Set<ComponentType>();
|
||||
for (let at of atypes) {
|
||||
for (let c of at.cmatch) {
|
||||
for (let f of c.fields) {
|
||||
if (f.name == fieldName)
|
||||
return c;
|
||||
comps.add(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Array.from(comps);
|
||||
}
|
||||
getComponentByName(name: string): ComponentType {
|
||||
return this.components[name];
|
||||
}
|
||||
singleComponentWithFieldName(atypes: ArchetypeMatch[], fieldName: string, where: string) {
|
||||
let components = this.componentsWithFieldName(atypes, fieldName);
|
||||
if (components.length == 0) {
|
||||
throw new Error(`cannot find component with field "${fieldName}" in ${where}`);
|
||||
}
|
||||
if (components.length > 1) {
|
||||
throw new Error(`ambiguous field name "${fieldName}" in ${where}`);
|
||||
}
|
||||
return components[0];
|
||||
}
|
||||
toJSON() {
|
||||
return JSON.stringify({
|
||||
components: this.components,
|
||||
|
@ -14,16 +14,18 @@ class ECSMain {
|
||||
let text = readFileSync(path, 'utf-8');
|
||||
try {
|
||||
this.compiler.parseFile(text, path);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
for (let err of this.compiler.errors) {
|
||||
console.log(`${err.path}:${err.line}:${err.start}: ${err.msg}`);
|
||||
if (this.compiler.errors.length == 0) {
|
||||
let file = new SourceFileExport();
|
||||
this.compiler.exportToFile(file);
|
||||
console.log(file.toString());
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
for (let err of this.compiler.errors) {
|
||||
console.error(`${err.path}:${err.line}:${err.start}: ${err.msg}`);
|
||||
}
|
||||
}
|
||||
let file = new SourceFileExport();
|
||||
this.compiler.exportToFile(file);
|
||||
console.log(file.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -181,7 +181,7 @@ export class Tokenizer {
|
||||
let tok = this.consumeToken();
|
||||
let tokstr = tok.str;
|
||||
if (strlist.indexOf(tokstr) < 0) {
|
||||
this.compileError(msg || `There should be a ${strlist.map((s) => `"${s}"`).join(' or ')} here, not "${tokstr}.`);
|
||||
this.compileError(msg || `There should be a ${strlist.map((s) => `"${s}"`).join(' or ')} here, not "${tokstr}".`);
|
||||
}
|
||||
return tok;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ const TEMPLATE2_a = `
|
||||
lda SWCHA
|
||||
sta {{$0}}
|
||||
`
|
||||
|
||||
const TEMPLATE2_b = `
|
||||
asl {{$0}}
|
||||
bcs {{@SkipMoveRight}}
|
||||
@ -308,18 +309,18 @@ function testECS() {
|
||||
// https://docs.unity3d.com/Packages/com.unity.entities@0.17/manual/ecs_systems.html
|
||||
em.defineSystem({
|
||||
name: 'frameloop',
|
||||
emits: ['preframe', 'kernel', 'postframe'],
|
||||
actions: [
|
||||
{ text: TEMPLATE1, event: 'start', select: 'once', query: { include: ['kernel'] } }
|
||||
{ text: TEMPLATE1, event: 'start', select: 'once', query: { include: ['kernel'] },
|
||||
emits: ['preframe', 'kernel', 'postframe'] }
|
||||
]
|
||||
})
|
||||
em.defineSystem({
|
||||
name: 'joyread',
|
||||
tempbytes: 1,
|
||||
emits: ['joyup', 'joydown', 'joyleft', 'joyright', 'joybutton'],
|
||||
actions: [
|
||||
{ text: TEMPLATE2_a, event: 'postframe', select: 'once', query: { include: ['player'] } },
|
||||
{ text: TEMPLATE2_b, event: 'postframe', select: 'each', query: { include: ['player'] } }
|
||||
{ text: TEMPLATE2_b, event: 'postframe', select: 'each', query: { include: ['player'] },
|
||||
emits: ['joyup', 'joydown', 'joyleft', 'joyright', 'joybutton'] }
|
||||
]
|
||||
});
|
||||
em.defineSystem({
|
||||
@ -406,17 +407,19 @@ Label:
|
||||
---
|
||||
end
|
||||
|
||||
comment ---
|
||||
|
||||
---
|
||||
|
||||
scope Root
|
||||
|
||||
entity kernel [Kernel]
|
||||
const lines = 100
|
||||
const lines = 0xc0
|
||||
const lines = $c0
|
||||
end
|
||||
|
||||
entity player1 [HasBitmap]
|
||||
const plyrindex = 0
|
||||
init height = 8
|
||||
init xpos = 100
|
||||
init ypos = 100
|
||||
init bitmap = 1
|
||||
end
|
||||
|
||||
end
|
||||
@ -433,6 +436,7 @@ end
|
||||
console.log(err);
|
||||
}
|
||||
console.log(c.tokens);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user