ecs: default field values
This commit is contained in:
parent
a444de693b
commit
07c0ae2f9c
|
@ -143,6 +143,7 @@ banks need to duplicate code and/or rodata
|
|||
- don't split critical code across banks
|
||||
need bank trampoline macro
|
||||
nested scopes for game modes? (title / demo / play)
|
||||
access parent data from child scope
|
||||
|
||||
critical data fields
|
||||
if accessed in critical section, make critical
|
||||
|
@ -150,4 +151,8 @@ ignore arrays that aren't referenced
|
|||
|
||||
use DASM for multipass?
|
||||
|
||||
default values for component fields
|
||||
processes
|
||||
take up at least one byte if stateful
|
||||
might need free list
|
||||
need jump table?
|
||||
you'd like to change "mode" from any event
|
||||
|
|
|
@ -139,7 +139,12 @@ export class ECSCompiler extends Tokenizer {
|
|||
let lo = this.expectInteger();
|
||||
this.expectToken('..');
|
||||
let hi = this.expectInteger();
|
||||
return { dtype: 'int', lo, hi } as IntType;
|
||||
// TODO: use default value?
|
||||
let defvalue;
|
||||
if (this.ifToken('default')) {
|
||||
defvalue = this.expectInteger();
|
||||
}
|
||||
return { dtype: 'int', lo, hi, defvalue } as IntType;
|
||||
}
|
||||
if (this.peekToken().str == '[') {
|
||||
return { dtype: 'ref', query: this.parseQuery() } as RefType;
|
||||
|
@ -392,8 +397,7 @@ export class ECSCompiler extends Tokenizer {
|
|||
entname = this.expectIdent().str;
|
||||
}
|
||||
let etype = this.parseEntityArchetype();
|
||||
let entity = this.currentScope.newEntity(etype);
|
||||
entity.name = entname;
|
||||
let entity = this.currentScope.newEntity(etype, entname);
|
||||
let cmd2: string;
|
||||
// TODO: remove init?
|
||||
while ((cmd2 = this.expectTokens(['const', 'init', 'var', 'decode', 'end']).str) != 'end') {
|
||||
|
|
|
@ -73,6 +73,24 @@ export class VCSSpriteDecoder extends LineDecoder {
|
|||
}
|
||||
}
|
||||
|
||||
export class VCSBitmapDecoder extends LineDecoder {
|
||||
parse() {
|
||||
let height = this.lines.length;
|
||||
let bitmapdata = new Uint8Array(height);
|
||||
for (let i=0; i<height; i++) {
|
||||
this.curline = height - 1 - i;
|
||||
let toks = this.lines[this.curline];
|
||||
this.assertTokens(toks, 1);
|
||||
bitmapdata[i] = this.decodeBits(toks[0], 8, true);
|
||||
}
|
||||
return {
|
||||
properties: {
|
||||
bitmapdata, height: height-1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class VCSPlayfieldDecoder extends LineDecoder {
|
||||
parse() {
|
||||
let height = this.lines.length;
|
||||
|
@ -178,6 +196,7 @@ export function newDecoder(name: string, text: string) : LineDecoder | undefined
|
|||
|
||||
const DECODERS = {
|
||||
'vcs_sprite': VCSSpriteDecoder,
|
||||
'vcs_bitmap': VCSBitmapDecoder,
|
||||
'vcs_playfield': VCSPlayfieldDecoder,
|
||||
'vcs_versatile': VCSVersatilePlayfieldDecoder,
|
||||
'vcs_bitmap48': VCSBitmap48Decoder,
|
||||
|
|
|
@ -156,6 +156,7 @@ export interface IntType {
|
|||
dtype: 'int'
|
||||
lo: number
|
||||
hi: number
|
||||
defvalue?: number
|
||||
}
|
||||
|
||||
export interface ArrayType {
|
||||
|
@ -1088,15 +1089,18 @@ export class EntityScope implements SourceLocated {
|
|||
) {
|
||||
parent?.childScopes.push(this);
|
||||
}
|
||||
newEntity(etype: EntityArchetype): Entity {
|
||||
newEntity(etype: EntityArchetype, name: string): Entity {
|
||||
// TODO: add parent ID? lock parent scope?
|
||||
// TODO: name identical check?
|
||||
if (name && this.getEntityByName(name))
|
||||
throw new ECSError(`already an entity named "${name}"`);
|
||||
let id = this.entities.length;
|
||||
etype = this.em.addArchetype(etype);
|
||||
let entity: Entity = { id, etype, consts: {}, inits: {} };
|
||||
for (let c of etype.components) {
|
||||
this.componentsInScope.add(c.name);
|
||||
}
|
||||
entity.name = name;
|
||||
this.entities.push(entity);
|
||||
return entity;
|
||||
}
|
||||
|
@ -1172,7 +1176,14 @@ export class EntityScope implements SourceLocated {
|
|||
} else {
|
||||
array.ehi = i;
|
||||
}
|
||||
//console.log(i,e.name,array,cfname);
|
||||
// set default values for entity/field
|
||||
if (ftype == 'init') {
|
||||
if (f.dtype == 'int' && f.defvalue !== undefined) {
|
||||
let ecfname = mkscopesymbol(this, c, f.name);
|
||||
if (e.inits[ecfname] == null)
|
||||
this.setInitValue(e, c, f, f.defvalue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: cull unused entity fields
|
||||
|
@ -1323,7 +1334,7 @@ export class EntityScope implements SourceLocated {
|
|||
let cfname = mksymbol(component, fieldName);
|
||||
let ecfname = mkscopesymbol(this, component, fieldName);
|
||||
if (e.consts[cfname] !== undefined) throw new ECSError(`"${fieldName}" is already defined as a constant`, e);
|
||||
if (e.inits[ecfname] !== undefined) throw new ECSError(`"${fieldName}" is already defined as a`, e);
|
||||
if (e.inits[ecfname] !== undefined) throw new ECSError(`"${fieldName}" is already defined as a variable`, e);
|
||||
if (type == 'const') e.consts[cfname] = value;
|
||||
if (type == 'init') e.inits[ecfname] = value;
|
||||
this.fieldtypes[cfname] = type;
|
||||
|
|
Loading…
Reference in New Issue